diff --git a/assets/fontawesome/css/all.min.css b/assets/fontawesome/css/all.min.css new file mode 100644 index 0000000..cd555f1 --- /dev/null +++ b/assets/fontawesome/css/all.min.css @@ -0,0 +1,9 @@ +/*! + * Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2023 Fonticons, Inc. + */ +.fa{font-family:var(--fa-style-family,"Font Awesome 6 Free");font-weight:var(--fa-style,900)}.fa,.fa-brands,.fa-classic,.fa-regular,.fa-sharp,.fa-solid,.fab,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display,inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fa-classic,.fa-regular,.fa-solid,.far,.fas{font-family:"Font Awesome 6 Free"}.fa-brands,.fab{font-family:"Font Awesome 6 Brands"}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.08333em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.07143em;vertical-align:.05357em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.04167em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin,2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(var(--fa-li-width, 2em)*-1);position:absolute;text-align:center;width:var(--fa-li-width,2em);line-height:inherit}.fa-border{border-radius:var(--fa-border-radius,.1em);border:var(--fa-border-width,.08em) var(--fa-border-style,solid) var(--fa-border-color,#eee);padding:var(--fa-border-padding,.2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin,.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin,.3em)}.fa-beat{-webkit-animation-name:fa-beat;animation-name:fa-beat;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-bounce{-webkit-animation-name:fa-bounce;animation-name:fa-bounce;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1))}.fa-fade{-webkit-animation-name:fa-fade;animation-name:fa-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-beat-fade,.fa-fade{-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s)}.fa-beat-fade{-webkit-animation-name:fa-beat-fade;animation-name:fa-beat-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-flip{-webkit-animation-name:fa-flip;animation-name:fa-flip;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-shake{-webkit-animation-name:fa-shake;animation-name:fa-shake;-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-shake,.fa-spin{-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal)}.fa-spin{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-duration:var(--fa-animation-duration,2s);animation-duration:var(--fa-animation-duration,2s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,linear);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin-reverse{--fa-animation-direction:reverse}.fa-pulse,.fa-spin-pulse{-webkit-animation-name:fa-spin;animation-name:fa-spin;-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,steps(8));animation-timing-function:var(--fa-animation-timing,steps(8))}@media (prefers-reduced-motion:reduce){.fa-beat,.fa-beat-fade,.fa-bounce,.fa-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{-webkit-animation-delay:-1ms;animation-delay:-1ms;-webkit-animation-duration:1ms;animation-duration:1ms;-webkit-animation-iteration-count:1;animation-iteration-count:1;-webkit-transition-delay:0s;transition-delay:0s;-webkit-transition-duration:0s;transition-duration:0s}}@-webkit-keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@keyframes fa-beat{0%,90%{-webkit-transform:scale(1);transform:scale(1)}45%{-webkit-transform:scale(var(--fa-beat-scale,1.25));transform:scale(var(--fa-beat-scale,1.25))}}@-webkit-keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@keyframes fa-bounce{0%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}10%{-webkit-transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0);transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{-webkit-transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em));transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{-webkit-transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0);transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{-webkit-transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em));transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}to{-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@-webkit-keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@-webkit-keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);-webkit-transform:scale(1);transform:scale(1)}50%{opacity:1;-webkit-transform:scale(var(--fa-beat-fade-scale,1.125));transform:scale(var(--fa-beat-fade-scale,1.125))}}@-webkit-keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@keyframes fa-flip{50%{-webkit-transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg));transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@-webkit-keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@keyframes fa-shake{0%{-webkit-transform:rotate(-15deg);transform:rotate(-15deg)}4%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}8%,24%{-webkit-transform:rotate(-18deg);transform:rotate(-18deg)}12%,28%{-webkit-transform:rotate(18deg);transform:rotate(18deg)}16%{-webkit-transform:rotate(-22deg);transform:rotate(-22deg)}20%{-webkit-transform:rotate(22deg);transform:rotate(22deg)}32%{-webkit-transform:rotate(-12deg);transform:rotate(-12deg)}36%{-webkit-transform:rotate(12deg);transform:rotate(12deg)}40%,to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}.fa-rotate-by{-webkit-transform:rotate(var(--fa-rotate-angle,none));transform:rotate(var(--fa-rotate-angle,none))}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%;z-index:var(--fa-stack-z-index,auto)}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:var(--fa-inverse,#fff)} + +.fa-0:before{content:"\30"}.fa-1:before{content:"\31"}.fa-2:before{content:"\32"}.fa-3:before{content:"\33"}.fa-4:before{content:"\34"}.fa-5:before{content:"\35"}.fa-6:before{content:"\36"}.fa-7:before{content:"\37"}.fa-8:before{content:"\38"}.fa-9:before{content:"\39"}.fa-fill-drip:before{content:"\f576"}.fa-arrows-to-circle:before{content:"\e4bd"}.fa-chevron-circle-right:before,.fa-circle-chevron-right:before{content:"\f138"}.fa-at:before{content:"\40"}.fa-trash-alt:before,.fa-trash-can:before{content:"\f2ed"}.fa-text-height:before{content:"\f034"}.fa-user-times:before,.fa-user-xmark:before{content:"\f235"}.fa-stethoscope:before{content:"\f0f1"}.fa-comment-alt:before,.fa-message:before{content:"\f27a"}.fa-info:before{content:"\f129"}.fa-compress-alt:before,.fa-down-left-and-up-right-to-center:before{content:"\f422"}.fa-explosion:before{content:"\e4e9"}.fa-file-alt:before,.fa-file-lines:before,.fa-file-text:before{content:"\f15c"}.fa-wave-square:before{content:"\f83e"}.fa-ring:before{content:"\f70b"}.fa-building-un:before{content:"\e4d9"}.fa-dice-three:before{content:"\f527"}.fa-calendar-alt:before,.fa-calendar-days:before{content:"\f073"}.fa-anchor-circle-check:before{content:"\e4aa"}.fa-building-circle-arrow-right:before{content:"\e4d1"}.fa-volleyball-ball:before,.fa-volleyball:before{content:"\f45f"}.fa-arrows-up-to-line:before{content:"\e4c2"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-circle-minus:before,.fa-minus-circle:before{content:"\f056"}.fa-door-open:before{content:"\f52b"}.fa-right-from-bracket:before,.fa-sign-out-alt:before{content:"\f2f5"}.fa-atom:before{content:"\f5d2"}.fa-soap:before{content:"\e06e"}.fa-heart-music-camera-bolt:before,.fa-icons:before{content:"\f86d"}.fa-microphone-alt-slash:before,.fa-microphone-lines-slash:before{content:"\f539"}.fa-bridge-circle-check:before{content:"\e4c9"}.fa-pump-medical:before{content:"\e06a"}.fa-fingerprint:before{content:"\f577"}.fa-hand-point-right:before{content:"\f0a4"}.fa-magnifying-glass-location:before,.fa-search-location:before{content:"\f689"}.fa-forward-step:before,.fa-step-forward:before{content:"\f051"}.fa-face-smile-beam:before,.fa-smile-beam:before{content:"\f5b8"}.fa-flag-checkered:before{content:"\f11e"}.fa-football-ball:before,.fa-football:before{content:"\f44e"}.fa-school-circle-exclamation:before{content:"\e56c"}.fa-crop:before{content:"\f125"}.fa-angle-double-down:before,.fa-angles-down:before{content:"\f103"}.fa-users-rectangle:before{content:"\e594"}.fa-people-roof:before{content:"\e537"}.fa-people-line:before{content:"\e534"}.fa-beer-mug-empty:before,.fa-beer:before{content:"\f0fc"}.fa-diagram-predecessor:before{content:"\e477"}.fa-arrow-up-long:before,.fa-long-arrow-up:before{content:"\f176"}.fa-burn:before,.fa-fire-flame-simple:before{content:"\f46a"}.fa-male:before,.fa-person:before{content:"\f183"}.fa-laptop:before{content:"\f109"}.fa-file-csv:before{content:"\f6dd"}.fa-menorah:before{content:"\f676"}.fa-truck-plane:before{content:"\e58f"}.fa-record-vinyl:before{content:"\f8d9"}.fa-face-grin-stars:before,.fa-grin-stars:before{content:"\f587"}.fa-bong:before{content:"\f55c"}.fa-pastafarianism:before,.fa-spaghetti-monster-flying:before{content:"\f67b"}.fa-arrow-down-up-across-line:before{content:"\e4af"}.fa-spoon:before,.fa-utensil-spoon:before{content:"\f2e5"}.fa-jar-wheat:before{content:"\e517"}.fa-envelopes-bulk:before,.fa-mail-bulk:before{content:"\f674"}.fa-file-circle-exclamation:before{content:"\e4eb"}.fa-circle-h:before,.fa-hospital-symbol:before{content:"\f47e"}.fa-pager:before{content:"\f815"}.fa-address-book:before,.fa-contact-book:before{content:"\f2b9"}.fa-strikethrough:before{content:"\f0cc"}.fa-k:before{content:"\4b"}.fa-landmark-flag:before{content:"\e51c"}.fa-pencil-alt:before,.fa-pencil:before{content:"\f303"}.fa-backward:before{content:"\f04a"}.fa-caret-right:before{content:"\f0da"}.fa-comments:before{content:"\f086"}.fa-file-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-code-pull-request:before{content:"\e13c"}.fa-clipboard-list:before{content:"\f46d"}.fa-truck-loading:before,.fa-truck-ramp-box:before{content:"\f4de"}.fa-user-check:before{content:"\f4fc"}.fa-vial-virus:before{content:"\e597"}.fa-sheet-plastic:before{content:"\e571"}.fa-blog:before{content:"\f781"}.fa-user-ninja:before{content:"\f504"}.fa-person-arrow-up-from-line:before{content:"\e539"}.fa-scroll-torah:before,.fa-torah:before{content:"\f6a0"}.fa-broom-ball:before,.fa-quidditch-broom-ball:before,.fa-quidditch:before{content:"\f458"}.fa-toggle-off:before{content:"\f204"}.fa-archive:before,.fa-box-archive:before{content:"\f187"}.fa-person-drowning:before{content:"\e545"}.fa-arrow-down-9-1:before,.fa-sort-numeric-desc:before,.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-face-grin-tongue-squint:before,.fa-grin-tongue-squint:before{content:"\f58a"}.fa-spray-can:before{content:"\f5bd"}.fa-truck-monster:before{content:"\f63b"}.fa-w:before{content:"\57"}.fa-earth-africa:before,.fa-globe-africa:before{content:"\f57c"}.fa-rainbow:before{content:"\f75b"}.fa-circle-notch:before{content:"\f1ce"}.fa-tablet-alt:before,.fa-tablet-screen-button:before{content:"\f3fa"}.fa-paw:before{content:"\f1b0"}.fa-cloud:before{content:"\f0c2"}.fa-trowel-bricks:before{content:"\e58a"}.fa-face-flushed:before,.fa-flushed:before{content:"\f579"}.fa-hospital-user:before{content:"\f80d"}.fa-tent-arrow-left-right:before{content:"\e57f"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-binoculars:before{content:"\f1e5"}.fa-microphone-slash:before{content:"\f131"}.fa-box-tissue:before{content:"\e05b"}.fa-motorcycle:before{content:"\f21c"}.fa-bell-concierge:before,.fa-concierge-bell:before{content:"\f562"}.fa-pen-ruler:before,.fa-pencil-ruler:before{content:"\f5ae"}.fa-people-arrows-left-right:before,.fa-people-arrows:before{content:"\e068"}.fa-mars-and-venus-burst:before{content:"\e523"}.fa-caret-square-right:before,.fa-square-caret-right:before{content:"\f152"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-sun-plant-wilt:before{content:"\e57a"}.fa-toilets-portable:before{content:"\e584"}.fa-hockey-puck:before{content:"\f453"}.fa-table:before{content:"\f0ce"}.fa-magnifying-glass-arrow-right:before{content:"\e521"}.fa-digital-tachograph:before,.fa-tachograph-digital:before{content:"\f566"}.fa-users-slash:before{content:"\e073"}.fa-clover:before{content:"\e139"}.fa-mail-reply:before,.fa-reply:before{content:"\f3e5"}.fa-star-and-crescent:before{content:"\f699"}.fa-house-fire:before{content:"\e50c"}.fa-minus-square:before,.fa-square-minus:before{content:"\f146"}.fa-helicopter:before{content:"\f533"}.fa-compass:before{content:"\f14e"}.fa-caret-square-down:before,.fa-square-caret-down:before{content:"\f150"}.fa-file-circle-question:before{content:"\e4ef"}.fa-laptop-code:before{content:"\f5fc"}.fa-swatchbook:before{content:"\f5c3"}.fa-prescription-bottle:before{content:"\f485"}.fa-bars:before,.fa-navicon:before{content:"\f0c9"}.fa-people-group:before{content:"\e533"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-heart-broken:before,.fa-heart-crack:before{content:"\f7a9"}.fa-external-link-square-alt:before,.fa-square-up-right:before{content:"\f360"}.fa-face-kiss-beam:before,.fa-kiss-beam:before{content:"\f597"}.fa-film:before{content:"\f008"}.fa-ruler-horizontal:before{content:"\f547"}.fa-people-robbery:before{content:"\e536"}.fa-lightbulb:before{content:"\f0eb"}.fa-caret-left:before{content:"\f0d9"}.fa-circle-exclamation:before,.fa-exclamation-circle:before{content:"\f06a"}.fa-school-circle-xmark:before{content:"\e56d"}.fa-arrow-right-from-bracket:before,.fa-sign-out:before{content:"\f08b"}.fa-chevron-circle-down:before,.fa-circle-chevron-down:before{content:"\f13a"}.fa-unlock-alt:before,.fa-unlock-keyhole:before{content:"\f13e"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-headphones-alt:before,.fa-headphones-simple:before{content:"\f58f"}.fa-sitemap:before{content:"\f0e8"}.fa-circle-dollar-to-slot:before,.fa-donate:before{content:"\f4b9"}.fa-memory:before{content:"\f538"}.fa-road-spikes:before{content:"\e568"}.fa-fire-burner:before{content:"\e4f1"}.fa-flag:before{content:"\f024"}.fa-hanukiah:before{content:"\f6e6"}.fa-feather:before{content:"\f52d"}.fa-volume-down:before,.fa-volume-low:before{content:"\f027"}.fa-comment-slash:before{content:"\f4b3"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-compress:before{content:"\f066"}.fa-wheat-alt:before,.fa-wheat-awn:before{content:"\e2cd"}.fa-ankh:before{content:"\f644"}.fa-hands-holding-child:before{content:"\e4fa"}.fa-asterisk:before{content:"\2a"}.fa-check-square:before,.fa-square-check:before{content:"\f14a"}.fa-peseta-sign:before{content:"\e221"}.fa-header:before,.fa-heading:before{content:"\f1dc"}.fa-ghost:before{content:"\f6e2"}.fa-list-squares:before,.fa-list:before{content:"\f03a"}.fa-phone-square-alt:before,.fa-square-phone-flip:before{content:"\f87b"}.fa-cart-plus:before{content:"\f217"}.fa-gamepad:before{content:"\f11b"}.fa-circle-dot:before,.fa-dot-circle:before{content:"\f192"}.fa-dizzy:before,.fa-face-dizzy:before{content:"\f567"}.fa-egg:before{content:"\f7fb"}.fa-house-medical-circle-xmark:before{content:"\e513"}.fa-campground:before{content:"\f6bb"}.fa-folder-plus:before{content:"\f65e"}.fa-futbol-ball:before,.fa-futbol:before,.fa-soccer-ball:before{content:"\f1e3"}.fa-paint-brush:before,.fa-paintbrush:before{content:"\f1fc"}.fa-lock:before{content:"\f023"}.fa-gas-pump:before{content:"\f52f"}.fa-hot-tub-person:before,.fa-hot-tub:before{content:"\f593"}.fa-map-location:before,.fa-map-marked:before{content:"\f59f"}.fa-house-flood-water:before{content:"\e50e"}.fa-tree:before{content:"\f1bb"}.fa-bridge-lock:before{content:"\e4cc"}.fa-sack-dollar:before{content:"\f81d"}.fa-edit:before,.fa-pen-to-square:before{content:"\f044"}.fa-car-side:before{content:"\f5e4"}.fa-share-alt:before,.fa-share-nodes:before{content:"\f1e0"}.fa-heart-circle-minus:before{content:"\e4ff"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-microscope:before{content:"\f610"}.fa-sink:before{content:"\e06d"}.fa-bag-shopping:before,.fa-shopping-bag:before{content:"\f290"}.fa-arrow-down-z-a:before,.fa-sort-alpha-desc:before,.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-mitten:before{content:"\f7b5"}.fa-person-rays:before{content:"\e54d"}.fa-users:before{content:"\f0c0"}.fa-eye-slash:before{content:"\f070"}.fa-flask-vial:before{content:"\e4f3"}.fa-hand-paper:before,.fa-hand:before{content:"\f256"}.fa-om:before{content:"\f679"}.fa-worm:before{content:"\e599"}.fa-house-circle-xmark:before{content:"\e50b"}.fa-plug:before{content:"\f1e6"}.fa-chevron-up:before{content:"\f077"}.fa-hand-spock:before{content:"\f259"}.fa-stopwatch:before{content:"\f2f2"}.fa-face-kiss:before,.fa-kiss:before{content:"\f596"}.fa-bridge-circle-xmark:before{content:"\e4cb"}.fa-face-grin-tongue:before,.fa-grin-tongue:before{content:"\f589"}.fa-chess-bishop:before{content:"\f43a"}.fa-face-grin-wink:before,.fa-grin-wink:before{content:"\f58c"}.fa-deaf:before,.fa-deafness:before,.fa-ear-deaf:before,.fa-hard-of-hearing:before{content:"\f2a4"}.fa-road-circle-check:before{content:"\e564"}.fa-dice-five:before{content:"\f523"}.fa-rss-square:before,.fa-square-rss:before{content:"\f143"}.fa-land-mine-on:before{content:"\e51b"}.fa-i-cursor:before{content:"\f246"}.fa-stamp:before{content:"\f5bf"}.fa-stairs:before{content:"\e289"}.fa-i:before{content:"\49"}.fa-hryvnia-sign:before,.fa-hryvnia:before{content:"\f6f2"}.fa-pills:before{content:"\f484"}.fa-face-grin-wide:before,.fa-grin-alt:before{content:"\f581"}.fa-tooth:before{content:"\f5c9"}.fa-v:before{content:"\56"}.fa-bangladeshi-taka-sign:before{content:"\e2e6"}.fa-bicycle:before{content:"\f206"}.fa-rod-asclepius:before,.fa-rod-snake:before,.fa-staff-aesculapius:before,.fa-staff-snake:before{content:"\e579"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-ambulance:before,.fa-truck-medical:before{content:"\f0f9"}.fa-wheat-awn-circle-exclamation:before{content:"\e598"}.fa-snowman:before{content:"\f7d0"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-road-barrier:before{content:"\e562"}.fa-school:before{content:"\f549"}.fa-igloo:before{content:"\f7ae"}.fa-joint:before{content:"\f595"}.fa-angle-right:before{content:"\f105"}.fa-horse:before{content:"\f6f0"}.fa-q:before{content:"\51"}.fa-g:before{content:"\47"}.fa-notes-medical:before{content:"\f481"}.fa-temperature-2:before,.fa-temperature-half:before,.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-dong-sign:before{content:"\e169"}.fa-capsules:before{content:"\f46b"}.fa-poo-bolt:before,.fa-poo-storm:before{content:"\f75a"}.fa-face-frown-open:before,.fa-frown-open:before{content:"\f57a"}.fa-hand-point-up:before{content:"\f0a6"}.fa-money-bill:before{content:"\f0d6"}.fa-bookmark:before{content:"\f02e"}.fa-align-justify:before{content:"\f039"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-helmet-un:before{content:"\e503"}.fa-bullseye:before{content:"\f140"}.fa-bacon:before{content:"\f7e5"}.fa-hand-point-down:before{content:"\f0a7"}.fa-arrow-up-from-bracket:before{content:"\e09a"}.fa-folder-blank:before,.fa-folder:before{content:"\f07b"}.fa-file-medical-alt:before,.fa-file-waveform:before{content:"\f478"}.fa-radiation:before{content:"\f7b9"}.fa-chart-simple:before{content:"\e473"}.fa-mars-stroke:before{content:"\f229"}.fa-vial:before{content:"\f492"}.fa-dashboard:before,.fa-gauge-med:before,.fa-gauge:before,.fa-tachometer-alt-average:before{content:"\f624"}.fa-magic-wand-sparkles:before,.fa-wand-magic-sparkles:before{content:"\e2ca"}.fa-e:before{content:"\45"}.fa-pen-alt:before,.fa-pen-clip:before{content:"\f305"}.fa-bridge-circle-exclamation:before{content:"\e4ca"}.fa-user:before{content:"\f007"}.fa-school-circle-check:before{content:"\e56b"}.fa-dumpster:before{content:"\f793"}.fa-shuttle-van:before,.fa-van-shuttle:before{content:"\f5b6"}.fa-building-user:before{content:"\e4da"}.fa-caret-square-left:before,.fa-square-caret-left:before{content:"\f191"}.fa-highlighter:before{content:"\f591"}.fa-key:before{content:"\f084"}.fa-bullhorn:before{content:"\f0a1"}.fa-globe:before{content:"\f0ac"}.fa-synagogue:before{content:"\f69b"}.fa-person-half-dress:before{content:"\e548"}.fa-road-bridge:before{content:"\e563"}.fa-location-arrow:before{content:"\f124"}.fa-c:before{content:"\43"}.fa-tablet-button:before{content:"\f10a"}.fa-building-lock:before{content:"\e4d6"}.fa-pizza-slice:before{content:"\f818"}.fa-money-bill-wave:before{content:"\f53a"}.fa-area-chart:before,.fa-chart-area:before{content:"\f1fe"}.fa-house-flag:before{content:"\e50d"}.fa-person-circle-minus:before{content:"\e540"}.fa-ban:before,.fa-cancel:before{content:"\f05e"}.fa-camera-rotate:before{content:"\e0d8"}.fa-air-freshener:before,.fa-spray-can-sparkles:before{content:"\f5d0"}.fa-star:before{content:"\f005"}.fa-repeat:before{content:"\f363"}.fa-cross:before{content:"\f654"}.fa-box:before{content:"\f466"}.fa-venus-mars:before{content:"\f228"}.fa-arrow-pointer:before,.fa-mouse-pointer:before{content:"\f245"}.fa-expand-arrows-alt:before,.fa-maximize:before{content:"\f31e"}.fa-charging-station:before{content:"\f5e7"}.fa-shapes:before,.fa-triangle-circle-square:before{content:"\f61f"}.fa-random:before,.fa-shuffle:before{content:"\f074"}.fa-person-running:before,.fa-running:before{content:"\f70c"}.fa-mobile-retro:before{content:"\e527"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-spider:before{content:"\f717"}.fa-hands-bound:before{content:"\e4f9"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-plane-circle-exclamation:before{content:"\e556"}.fa-x-ray:before{content:"\f497"}.fa-spell-check:before{content:"\f891"}.fa-slash:before{content:"\f715"}.fa-computer-mouse:before,.fa-mouse:before{content:"\f8cc"}.fa-arrow-right-to-bracket:before,.fa-sign-in:before{content:"\f090"}.fa-shop-slash:before,.fa-store-alt-slash:before{content:"\e070"}.fa-server:before{content:"\f233"}.fa-virus-covid-slash:before{content:"\e4a9"}.fa-shop-lock:before{content:"\e4a5"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-blender-phone:before{content:"\f6b6"}.fa-building-wheat:before{content:"\e4db"}.fa-person-breastfeeding:before{content:"\e53a"}.fa-right-to-bracket:before,.fa-sign-in-alt:before{content:"\f2f6"}.fa-venus:before{content:"\f221"}.fa-passport:before{content:"\f5ab"}.fa-heart-pulse:before,.fa-heartbeat:before{content:"\f21e"}.fa-people-carry-box:before,.fa-people-carry:before{content:"\f4ce"}.fa-temperature-high:before{content:"\f769"}.fa-microchip:before{content:"\f2db"}.fa-crown:before{content:"\f521"}.fa-weight-hanging:before{content:"\f5cd"}.fa-xmarks-lines:before{content:"\e59a"}.fa-file-prescription:before{content:"\f572"}.fa-weight-scale:before,.fa-weight:before{content:"\f496"}.fa-user-friends:before,.fa-user-group:before{content:"\f500"}.fa-arrow-up-a-z:before,.fa-sort-alpha-up:before{content:"\f15e"}.fa-chess-knight:before{content:"\f441"}.fa-face-laugh-squint:before,.fa-laugh-squint:before{content:"\f59b"}.fa-wheelchair:before{content:"\f193"}.fa-arrow-circle-up:before,.fa-circle-arrow-up:before{content:"\f0aa"}.fa-toggle-on:before{content:"\f205"}.fa-person-walking:before,.fa-walking:before{content:"\f554"}.fa-l:before{content:"\4c"}.fa-fire:before{content:"\f06d"}.fa-bed-pulse:before,.fa-procedures:before{content:"\f487"}.fa-shuttle-space:before,.fa-space-shuttle:before{content:"\f197"}.fa-face-laugh:before,.fa-laugh:before{content:"\f599"}.fa-folder-open:before{content:"\f07c"}.fa-heart-circle-plus:before{content:"\e500"}.fa-code-fork:before{content:"\e13b"}.fa-city:before{content:"\f64f"}.fa-microphone-alt:before,.fa-microphone-lines:before{content:"\f3c9"}.fa-pepper-hot:before{content:"\f816"}.fa-unlock:before{content:"\f09c"}.fa-colon-sign:before{content:"\e140"}.fa-headset:before{content:"\f590"}.fa-store-slash:before{content:"\e071"}.fa-road-circle-xmark:before{content:"\e566"}.fa-user-minus:before{content:"\f503"}.fa-mars-stroke-up:before,.fa-mars-stroke-v:before{content:"\f22a"}.fa-champagne-glasses:before,.fa-glass-cheers:before{content:"\f79f"}.fa-clipboard:before{content:"\f328"}.fa-house-circle-exclamation:before{content:"\e50a"}.fa-file-arrow-up:before,.fa-file-upload:before{content:"\f574"}.fa-wifi-3:before,.fa-wifi-strong:before,.fa-wifi:before{content:"\f1eb"}.fa-bath:before,.fa-bathtub:before{content:"\f2cd"}.fa-underline:before{content:"\f0cd"}.fa-user-edit:before,.fa-user-pen:before{content:"\f4ff"}.fa-signature:before{content:"\f5b7"}.fa-stroopwafel:before{content:"\f551"}.fa-bold:before{content:"\f032"}.fa-anchor-lock:before{content:"\e4ad"}.fa-building-ngo:before{content:"\e4d7"}.fa-manat-sign:before{content:"\e1d5"}.fa-not-equal:before{content:"\f53e"}.fa-border-style:before,.fa-border-top-left:before{content:"\f853"}.fa-map-location-dot:before,.fa-map-marked-alt:before{content:"\f5a0"}.fa-jedi:before{content:"\f669"}.fa-poll:before,.fa-square-poll-vertical:before{content:"\f681"}.fa-mug-hot:before{content:"\f7b6"}.fa-battery-car:before,.fa-car-battery:before{content:"\f5df"}.fa-gift:before{content:"\f06b"}.fa-dice-two:before{content:"\f528"}.fa-chess-queen:before{content:"\f445"}.fa-glasses:before{content:"\f530"}.fa-chess-board:before{content:"\f43c"}.fa-building-circle-check:before{content:"\e4d2"}.fa-person-chalkboard:before{content:"\e53d"}.fa-mars-stroke-h:before,.fa-mars-stroke-right:before{content:"\f22b"}.fa-hand-back-fist:before,.fa-hand-rock:before{content:"\f255"}.fa-caret-square-up:before,.fa-square-caret-up:before{content:"\f151"}.fa-cloud-showers-water:before{content:"\e4e4"}.fa-bar-chart:before,.fa-chart-bar:before{content:"\f080"}.fa-hands-bubbles:before,.fa-hands-wash:before{content:"\e05e"}.fa-less-than-equal:before{content:"\f537"}.fa-train:before{content:"\f238"}.fa-eye-low-vision:before,.fa-low-vision:before{content:"\f2a8"}.fa-crow:before{content:"\f520"}.fa-sailboat:before{content:"\e445"}.fa-window-restore:before{content:"\f2d2"}.fa-plus-square:before,.fa-square-plus:before{content:"\f0fe"}.fa-torii-gate:before{content:"\f6a1"}.fa-frog:before{content:"\f52e"}.fa-bucket:before{content:"\e4cf"}.fa-image:before{content:"\f03e"}.fa-microphone:before{content:"\f130"}.fa-cow:before{content:"\f6c8"}.fa-caret-up:before{content:"\f0d8"}.fa-screwdriver:before{content:"\f54a"}.fa-folder-closed:before{content:"\e185"}.fa-house-tsunami:before{content:"\e515"}.fa-square-nfi:before{content:"\e576"}.fa-arrow-up-from-ground-water:before{content:"\e4b5"}.fa-glass-martini-alt:before,.fa-martini-glass:before{content:"\f57b"}.fa-rotate-back:before,.fa-rotate-backward:before,.fa-rotate-left:before,.fa-undo-alt:before{content:"\f2ea"}.fa-columns:before,.fa-table-columns:before{content:"\f0db"}.fa-lemon:before{content:"\f094"}.fa-head-side-mask:before{content:"\e063"}.fa-handshake:before{content:"\f2b5"}.fa-gem:before{content:"\f3a5"}.fa-dolly-box:before,.fa-dolly:before{content:"\f472"}.fa-smoking:before{content:"\f48d"}.fa-compress-arrows-alt:before,.fa-minimize:before{content:"\f78c"}.fa-monument:before{content:"\f5a6"}.fa-snowplow:before{content:"\f7d2"}.fa-angle-double-right:before,.fa-angles-right:before{content:"\f101"}.fa-cannabis:before{content:"\f55f"}.fa-circle-play:before,.fa-play-circle:before{content:"\f144"}.fa-tablets:before{content:"\f490"}.fa-ethernet:before{content:"\f796"}.fa-eur:before,.fa-euro-sign:before,.fa-euro:before{content:"\f153"}.fa-chair:before{content:"\f6c0"}.fa-check-circle:before,.fa-circle-check:before{content:"\f058"}.fa-circle-stop:before,.fa-stop-circle:before{content:"\f28d"}.fa-compass-drafting:before,.fa-drafting-compass:before{content:"\f568"}.fa-plate-wheat:before{content:"\e55a"}.fa-icicles:before{content:"\f7ad"}.fa-person-shelter:before{content:"\e54f"}.fa-neuter:before{content:"\f22c"}.fa-id-badge:before{content:"\f2c1"}.fa-marker:before{content:"\f5a1"}.fa-face-laugh-beam:before,.fa-laugh-beam:before{content:"\f59a"}.fa-helicopter-symbol:before{content:"\e502"}.fa-universal-access:before{content:"\f29a"}.fa-chevron-circle-up:before,.fa-circle-chevron-up:before{content:"\f139"}.fa-lari-sign:before{content:"\e1c8"}.fa-volcano:before{content:"\f770"}.fa-person-walking-dashed-line-arrow-right:before{content:"\e553"}.fa-gbp:before,.fa-pound-sign:before,.fa-sterling-sign:before{content:"\f154"}.fa-viruses:before{content:"\e076"}.fa-square-person-confined:before{content:"\e577"}.fa-user-tie:before{content:"\f508"}.fa-arrow-down-long:before,.fa-long-arrow-down:before{content:"\f175"}.fa-tent-arrow-down-to-line:before{content:"\e57e"}.fa-certificate:before{content:"\f0a3"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-suitcase:before{content:"\f0f2"}.fa-person-skating:before,.fa-skating:before{content:"\f7c5"}.fa-filter-circle-dollar:before,.fa-funnel-dollar:before{content:"\f662"}.fa-camera-retro:before{content:"\f083"}.fa-arrow-circle-down:before,.fa-circle-arrow-down:before{content:"\f0ab"}.fa-arrow-right-to-file:before,.fa-file-import:before{content:"\f56f"}.fa-external-link-square:before,.fa-square-arrow-up-right:before{content:"\f14c"}.fa-box-open:before{content:"\f49e"}.fa-scroll:before{content:"\f70e"}.fa-spa:before{content:"\f5bb"}.fa-location-pin-lock:before{content:"\e51f"}.fa-pause:before{content:"\f04c"}.fa-hill-avalanche:before{content:"\e507"}.fa-temperature-0:before,.fa-temperature-empty:before,.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-bomb:before{content:"\f1e2"}.fa-registered:before{content:"\f25d"}.fa-address-card:before,.fa-contact-card:before,.fa-vcard:before{content:"\f2bb"}.fa-balance-scale-right:before,.fa-scale-unbalanced-flip:before{content:"\f516"}.fa-subscript:before{content:"\f12c"}.fa-diamond-turn-right:before,.fa-directions:before{content:"\f5eb"}.fa-burst:before{content:"\e4dc"}.fa-house-laptop:before,.fa-laptop-house:before{content:"\e066"}.fa-face-tired:before,.fa-tired:before{content:"\f5c8"}.fa-money-bills:before{content:"\e1f3"}.fa-smog:before{content:"\f75f"}.fa-crutch:before{content:"\f7f7"}.fa-cloud-arrow-up:before,.fa-cloud-upload-alt:before,.fa-cloud-upload:before{content:"\f0ee"}.fa-palette:before{content:"\f53f"}.fa-arrows-turn-right:before{content:"\e4c0"}.fa-vest:before{content:"\e085"}.fa-ferry:before{content:"\e4ea"}.fa-arrows-down-to-people:before{content:"\e4b9"}.fa-seedling:before,.fa-sprout:before{content:"\f4d8"}.fa-arrows-alt-h:before,.fa-left-right:before{content:"\f337"}.fa-boxes-packing:before{content:"\e4c7"}.fa-arrow-circle-left:before,.fa-circle-arrow-left:before{content:"\f0a8"}.fa-group-arrows-rotate:before{content:"\e4f6"}.fa-bowl-food:before{content:"\e4c6"}.fa-candy-cane:before{content:"\f786"}.fa-arrow-down-wide-short:before,.fa-sort-amount-asc:before,.fa-sort-amount-down:before{content:"\f160"}.fa-cloud-bolt:before,.fa-thunderstorm:before{content:"\f76c"}.fa-remove-format:before,.fa-text-slash:before{content:"\f87d"}.fa-face-smile-wink:before,.fa-smile-wink:before{content:"\f4da"}.fa-file-word:before{content:"\f1c2"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-arrows-h:before,.fa-arrows-left-right:before{content:"\f07e"}.fa-house-lock:before{content:"\e510"}.fa-cloud-arrow-down:before,.fa-cloud-download-alt:before,.fa-cloud-download:before{content:"\f0ed"}.fa-children:before{content:"\e4e1"}.fa-blackboard:before,.fa-chalkboard:before{content:"\f51b"}.fa-user-alt-slash:before,.fa-user-large-slash:before{content:"\f4fa"}.fa-envelope-open:before{content:"\f2b6"}.fa-handshake-alt-slash:before,.fa-handshake-simple-slash:before{content:"\e05f"}.fa-mattress-pillow:before{content:"\e525"}.fa-guarani-sign:before{content:"\e19a"}.fa-arrows-rotate:before,.fa-refresh:before,.fa-sync:before{content:"\f021"}.fa-fire-extinguisher:before{content:"\f134"}.fa-cruzeiro-sign:before{content:"\e152"}.fa-greater-than-equal:before{content:"\f532"}.fa-shield-alt:before,.fa-shield-halved:before{content:"\f3ed"}.fa-atlas:before,.fa-book-atlas:before{content:"\f558"}.fa-virus:before{content:"\e074"}.fa-envelope-circle-check:before{content:"\e4e8"}.fa-layer-group:before{content:"\f5fd"}.fa-arrows-to-dot:before{content:"\e4be"}.fa-archway:before{content:"\f557"}.fa-heart-circle-check:before{content:"\e4fd"}.fa-house-chimney-crack:before,.fa-house-damage:before{content:"\f6f1"}.fa-file-archive:before,.fa-file-zipper:before{content:"\f1c6"}.fa-square:before{content:"\f0c8"}.fa-glass-martini:before,.fa-martini-glass-empty:before{content:"\f000"}.fa-couch:before{content:"\f4b8"}.fa-cedi-sign:before{content:"\e0df"}.fa-italic:before{content:"\f033"}.fa-church:before{content:"\f51d"}.fa-comments-dollar:before{content:"\f653"}.fa-democrat:before{content:"\f747"}.fa-z:before{content:"\5a"}.fa-person-skiing:before,.fa-skiing:before{content:"\f7c9"}.fa-road-lock:before{content:"\e567"}.fa-a:before{content:"\41"}.fa-temperature-arrow-down:before,.fa-temperature-down:before{content:"\e03f"}.fa-feather-alt:before,.fa-feather-pointed:before{content:"\f56b"}.fa-p:before{content:"\50"}.fa-snowflake:before{content:"\f2dc"}.fa-newspaper:before{content:"\f1ea"}.fa-ad:before,.fa-rectangle-ad:before{content:"\f641"}.fa-arrow-circle-right:before,.fa-circle-arrow-right:before{content:"\f0a9"}.fa-filter-circle-xmark:before{content:"\e17b"}.fa-locust:before{content:"\e520"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-list-1-2:before,.fa-list-numeric:before,.fa-list-ol:before{content:"\f0cb"}.fa-person-dress-burst:before{content:"\e544"}.fa-money-check-alt:before,.fa-money-check-dollar:before{content:"\f53d"}.fa-vector-square:before{content:"\f5cb"}.fa-bread-slice:before{content:"\f7ec"}.fa-language:before{content:"\f1ab"}.fa-face-kiss-wink-heart:before,.fa-kiss-wink-heart:before{content:"\f598"}.fa-filter:before{content:"\f0b0"}.fa-question:before{content:"\3f"}.fa-file-signature:before{content:"\f573"}.fa-arrows-alt:before,.fa-up-down-left-right:before{content:"\f0b2"}.fa-house-chimney-user:before{content:"\e065"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-puzzle-piece:before{content:"\f12e"}.fa-money-check:before{content:"\f53c"}.fa-star-half-alt:before,.fa-star-half-stroke:before{content:"\f5c0"}.fa-code:before{content:"\f121"}.fa-glass-whiskey:before,.fa-whiskey-glass:before{content:"\f7a0"}.fa-building-circle-exclamation:before{content:"\e4d3"}.fa-magnifying-glass-chart:before{content:"\e522"}.fa-arrow-up-right-from-square:before,.fa-external-link:before{content:"\f08e"}.fa-cubes-stacked:before{content:"\e4e6"}.fa-krw:before,.fa-won-sign:before,.fa-won:before{content:"\f159"}.fa-virus-covid:before{content:"\e4a8"}.fa-austral-sign:before{content:"\e0a9"}.fa-f:before{content:"\46"}.fa-leaf:before{content:"\f06c"}.fa-road:before{content:"\f018"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-person-circle-plus:before{content:"\e541"}.fa-chart-pie:before,.fa-pie-chart:before{content:"\f200"}.fa-bolt-lightning:before{content:"\e0b7"}.fa-sack-xmark:before{content:"\e56a"}.fa-file-excel:before{content:"\f1c3"}.fa-file-contract:before{content:"\f56c"}.fa-fish-fins:before{content:"\e4f2"}.fa-building-flag:before{content:"\e4d5"}.fa-face-grin-beam:before,.fa-grin-beam:before{content:"\f582"}.fa-object-ungroup:before{content:"\f248"}.fa-poop:before{content:"\f619"}.fa-location-pin:before,.fa-map-marker:before{content:"\f041"}.fa-kaaba:before{content:"\f66b"}.fa-toilet-paper:before{content:"\f71e"}.fa-hard-hat:before,.fa-hat-hard:before,.fa-helmet-safety:before{content:"\f807"}.fa-eject:before{content:"\f052"}.fa-arrow-alt-circle-right:before,.fa-circle-right:before{content:"\f35a"}.fa-plane-circle-check:before{content:"\e555"}.fa-face-rolling-eyes:before,.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-object-group:before{content:"\f247"}.fa-chart-line:before,.fa-line-chart:before{content:"\f201"}.fa-mask-ventilator:before{content:"\e524"}.fa-arrow-right:before{content:"\f061"}.fa-map-signs:before,.fa-signs-post:before{content:"\f277"}.fa-cash-register:before{content:"\f788"}.fa-person-circle-question:before{content:"\e542"}.fa-h:before{content:"\48"}.fa-tarp:before{content:"\e57b"}.fa-screwdriver-wrench:before,.fa-tools:before{content:"\f7d9"}.fa-arrows-to-eye:before{content:"\e4bf"}.fa-plug-circle-bolt:before{content:"\e55b"}.fa-heart:before{content:"\f004"}.fa-mars-and-venus:before{content:"\f224"}.fa-home-user:before,.fa-house-user:before{content:"\e1b0"}.fa-dumpster-fire:before{content:"\f794"}.fa-house-crack:before{content:"\e3b1"}.fa-cocktail:before,.fa-martini-glass-citrus:before{content:"\f561"}.fa-face-surprise:before,.fa-surprise:before{content:"\f5c2"}.fa-bottle-water:before{content:"\e4c5"}.fa-circle-pause:before,.fa-pause-circle:before{content:"\f28b"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-apple-alt:before,.fa-apple-whole:before{content:"\f5d1"}.fa-kitchen-set:before{content:"\e51a"}.fa-r:before{content:"\52"}.fa-temperature-1:before,.fa-temperature-quarter:before,.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-cube:before{content:"\f1b2"}.fa-bitcoin-sign:before{content:"\e0b4"}.fa-shield-dog:before{content:"\e573"}.fa-solar-panel:before{content:"\f5ba"}.fa-lock-open:before{content:"\f3c1"}.fa-elevator:before{content:"\e16d"}.fa-money-bill-transfer:before{content:"\e528"}.fa-money-bill-trend-up:before{content:"\e529"}.fa-house-flood-water-circle-arrow-right:before{content:"\e50f"}.fa-poll-h:before,.fa-square-poll-horizontal:before{content:"\f682"}.fa-circle:before{content:"\f111"}.fa-backward-fast:before,.fa-fast-backward:before{content:"\f049"}.fa-recycle:before{content:"\f1b8"}.fa-user-astronaut:before{content:"\f4fb"}.fa-plane-slash:before{content:"\e069"}.fa-trademark:before{content:"\f25c"}.fa-basketball-ball:before,.fa-basketball:before{content:"\f434"}.fa-satellite-dish:before{content:"\f7c0"}.fa-arrow-alt-circle-up:before,.fa-circle-up:before{content:"\f35b"}.fa-mobile-alt:before,.fa-mobile-screen-button:before{content:"\f3cd"}.fa-volume-high:before,.fa-volume-up:before{content:"\f028"}.fa-users-rays:before{content:"\e593"}.fa-wallet:before{content:"\f555"}.fa-clipboard-check:before{content:"\f46c"}.fa-file-audio:before{content:"\f1c7"}.fa-burger:before,.fa-hamburger:before{content:"\f805"}.fa-wrench:before{content:"\f0ad"}.fa-bugs:before{content:"\e4d0"}.fa-rupee-sign:before,.fa-rupee:before{content:"\f156"}.fa-file-image:before{content:"\f1c5"}.fa-circle-question:before,.fa-question-circle:before{content:"\f059"}.fa-plane-departure:before{content:"\f5b0"}.fa-handshake-slash:before{content:"\e060"}.fa-book-bookmark:before{content:"\e0bb"}.fa-code-branch:before{content:"\f126"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-bridge:before{content:"\e4c8"}.fa-phone-alt:before,.fa-phone-flip:before{content:"\f879"}.fa-truck-front:before{content:"\e2b7"}.fa-cat:before{content:"\f6be"}.fa-anchor-circle-exclamation:before{content:"\e4ab"}.fa-truck-field:before{content:"\e58d"}.fa-route:before{content:"\f4d7"}.fa-clipboard-question:before{content:"\e4e3"}.fa-panorama:before{content:"\e209"}.fa-comment-medical:before{content:"\f7f5"}.fa-teeth-open:before{content:"\f62f"}.fa-file-circle-minus:before{content:"\e4ed"}.fa-tags:before{content:"\f02c"}.fa-wine-glass:before{content:"\f4e3"}.fa-fast-forward:before,.fa-forward-fast:before{content:"\f050"}.fa-face-meh-blank:before,.fa-meh-blank:before{content:"\f5a4"}.fa-parking:before,.fa-square-parking:before{content:"\f540"}.fa-house-signal:before{content:"\e012"}.fa-bars-progress:before,.fa-tasks-alt:before{content:"\f828"}.fa-faucet-drip:before{content:"\e006"}.fa-cart-flatbed:before,.fa-dolly-flatbed:before{content:"\f474"}.fa-ban-smoking:before,.fa-smoking-ban:before{content:"\f54d"}.fa-terminal:before{content:"\f120"}.fa-mobile-button:before{content:"\f10b"}.fa-house-medical-flag:before{content:"\e514"}.fa-basket-shopping:before,.fa-shopping-basket:before{content:"\f291"}.fa-tape:before{content:"\f4db"}.fa-bus-alt:before,.fa-bus-simple:before{content:"\f55e"}.fa-eye:before{content:"\f06e"}.fa-face-sad-cry:before,.fa-sad-cry:before{content:"\f5b3"}.fa-audio-description:before{content:"\f29e"}.fa-person-military-to-person:before{content:"\e54c"}.fa-file-shield:before{content:"\e4f0"}.fa-user-slash:before{content:"\f506"}.fa-pen:before{content:"\f304"}.fa-tower-observation:before{content:"\e586"}.fa-file-code:before{content:"\f1c9"}.fa-signal-5:before,.fa-signal-perfect:before,.fa-signal:before{content:"\f012"}.fa-bus:before{content:"\f207"}.fa-heart-circle-xmark:before{content:"\e501"}.fa-home-lg:before,.fa-house-chimney:before{content:"\e3af"}.fa-window-maximize:before{content:"\f2d0"}.fa-face-frown:before,.fa-frown:before{content:"\f119"}.fa-prescription:before{content:"\f5b1"}.fa-shop:before,.fa-store-alt:before{content:"\f54f"}.fa-floppy-disk:before,.fa-save:before{content:"\f0c7"}.fa-vihara:before{content:"\f6a7"}.fa-balance-scale-left:before,.fa-scale-unbalanced:before{content:"\f515"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-comment-dots:before,.fa-commenting:before{content:"\f4ad"}.fa-plant-wilt:before{content:"\e5aa"}.fa-diamond:before{content:"\f219"}.fa-face-grin-squint:before,.fa-grin-squint:before{content:"\f585"}.fa-hand-holding-dollar:before,.fa-hand-holding-usd:before{content:"\f4c0"}.fa-bacterium:before{content:"\e05a"}.fa-hand-pointer:before{content:"\f25a"}.fa-drum-steelpan:before{content:"\f56a"}.fa-hand-scissors:before{content:"\f257"}.fa-hands-praying:before,.fa-praying-hands:before{content:"\f684"}.fa-arrow-right-rotate:before,.fa-arrow-rotate-forward:before,.fa-arrow-rotate-right:before,.fa-redo:before{content:"\f01e"}.fa-biohazard:before{content:"\f780"}.fa-location-crosshairs:before,.fa-location:before{content:"\f601"}.fa-mars-double:before{content:"\f227"}.fa-child-dress:before{content:"\e59c"}.fa-users-between-lines:before{content:"\e591"}.fa-lungs-virus:before{content:"\e067"}.fa-face-grin-tears:before,.fa-grin-tears:before{content:"\f588"}.fa-phone:before{content:"\f095"}.fa-calendar-times:before,.fa-calendar-xmark:before{content:"\f273"}.fa-child-reaching:before{content:"\e59d"}.fa-head-side-virus:before{content:"\e064"}.fa-user-cog:before,.fa-user-gear:before{content:"\f4fe"}.fa-arrow-up-1-9:before,.fa-sort-numeric-up:before{content:"\f163"}.fa-door-closed:before{content:"\f52a"}.fa-shield-virus:before{content:"\e06c"}.fa-dice-six:before{content:"\f526"}.fa-mosquito-net:before{content:"\e52c"}.fa-bridge-water:before{content:"\e4ce"}.fa-person-booth:before{content:"\f756"}.fa-text-width:before{content:"\f035"}.fa-hat-wizard:before{content:"\f6e8"}.fa-pen-fancy:before{content:"\f5ac"}.fa-digging:before,.fa-person-digging:before{content:"\f85e"}.fa-trash:before{content:"\f1f8"}.fa-gauge-simple-med:before,.fa-gauge-simple:before,.fa-tachometer-average:before{content:"\f629"}.fa-book-medical:before{content:"\f7e6"}.fa-poo:before{content:"\f2fe"}.fa-quote-right-alt:before,.fa-quote-right:before{content:"\f10e"}.fa-shirt:before,.fa-t-shirt:before,.fa-tshirt:before{content:"\f553"}.fa-cubes:before{content:"\f1b3"}.fa-divide:before{content:"\f529"}.fa-tenge-sign:before,.fa-tenge:before{content:"\f7d7"}.fa-headphones:before{content:"\f025"}.fa-hands-holding:before{content:"\f4c2"}.fa-hands-clapping:before{content:"\e1a8"}.fa-republican:before{content:"\f75e"}.fa-arrow-left:before{content:"\f060"}.fa-person-circle-xmark:before{content:"\e543"}.fa-ruler:before{content:"\f545"}.fa-align-left:before{content:"\f036"}.fa-dice-d6:before{content:"\f6d1"}.fa-restroom:before{content:"\f7bd"}.fa-j:before{content:"\4a"}.fa-users-viewfinder:before{content:"\e595"}.fa-file-video:before{content:"\f1c8"}.fa-external-link-alt:before,.fa-up-right-from-square:before{content:"\f35d"}.fa-table-cells:before,.fa-th:before{content:"\f00a"}.fa-file-pdf:before{content:"\f1c1"}.fa-bible:before,.fa-book-bible:before{content:"\f647"}.fa-o:before{content:"\4f"}.fa-medkit:before,.fa-suitcase-medical:before{content:"\f0fa"}.fa-user-secret:before{content:"\f21b"}.fa-otter:before{content:"\f700"}.fa-female:before,.fa-person-dress:before{content:"\f182"}.fa-comment-dollar:before{content:"\f651"}.fa-briefcase-clock:before,.fa-business-time:before{content:"\f64a"}.fa-table-cells-large:before,.fa-th-large:before{content:"\f009"}.fa-book-tanakh:before,.fa-tanakh:before{content:"\f827"}.fa-phone-volume:before,.fa-volume-control-phone:before{content:"\f2a0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-clipboard-user:before{content:"\f7f3"}.fa-child:before{content:"\f1ae"}.fa-lira-sign:before{content:"\f195"}.fa-satellite:before{content:"\f7bf"}.fa-plane-lock:before{content:"\e558"}.fa-tag:before{content:"\f02b"}.fa-comment:before{content:"\f075"}.fa-birthday-cake:before,.fa-cake-candles:before,.fa-cake:before{content:"\f1fd"}.fa-envelope:before{content:"\f0e0"}.fa-angle-double-up:before,.fa-angles-up:before{content:"\f102"}.fa-paperclip:before{content:"\f0c6"}.fa-arrow-right-to-city:before{content:"\e4b3"}.fa-ribbon:before{content:"\f4d6"}.fa-lungs:before{content:"\f604"}.fa-arrow-up-9-1:before,.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-litecoin-sign:before{content:"\e1d3"}.fa-border-none:before{content:"\f850"}.fa-circle-nodes:before{content:"\e4e2"}.fa-parachute-box:before{content:"\f4cd"}.fa-indent:before{content:"\f03c"}.fa-truck-field-un:before{content:"\e58e"}.fa-hourglass-empty:before,.fa-hourglass:before{content:"\f254"}.fa-mountain:before{content:"\f6fc"}.fa-user-doctor:before,.fa-user-md:before{content:"\f0f0"}.fa-circle-info:before,.fa-info-circle:before{content:"\f05a"}.fa-cloud-meatball:before{content:"\f73b"}.fa-camera-alt:before,.fa-camera:before{content:"\f030"}.fa-square-virus:before{content:"\e578"}.fa-meteor:before{content:"\f753"}.fa-car-on:before{content:"\e4dd"}.fa-sleigh:before{content:"\f7cc"}.fa-arrow-down-1-9:before,.fa-sort-numeric-asc:before,.fa-sort-numeric-down:before{content:"\f162"}.fa-hand-holding-droplet:before,.fa-hand-holding-water:before{content:"\f4c1"}.fa-water:before{content:"\f773"}.fa-calendar-check:before{content:"\f274"}.fa-braille:before{content:"\f2a1"}.fa-prescription-bottle-alt:before,.fa-prescription-bottle-medical:before{content:"\f486"}.fa-landmark:before{content:"\f66f"}.fa-truck:before{content:"\f0d1"}.fa-crosshairs:before{content:"\f05b"}.fa-person-cane:before{content:"\e53c"}.fa-tent:before{content:"\e57d"}.fa-vest-patches:before{content:"\e086"}.fa-check-double:before{content:"\f560"}.fa-arrow-down-a-z:before,.fa-sort-alpha-asc:before,.fa-sort-alpha-down:before{content:"\f15d"}.fa-money-bill-wheat:before{content:"\e52a"}.fa-cookie:before{content:"\f563"}.fa-arrow-left-rotate:before,.fa-arrow-rotate-back:before,.fa-arrow-rotate-backward:before,.fa-arrow-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-hard-drive:before,.fa-hdd:before{content:"\f0a0"}.fa-face-grin-squint-tears:before,.fa-grin-squint-tears:before{content:"\f586"}.fa-dumbbell:before{content:"\f44b"}.fa-list-alt:before,.fa-rectangle-list:before{content:"\f022"}.fa-tarp-droplet:before{content:"\e57c"}.fa-house-medical-circle-check:before{content:"\e511"}.fa-person-skiing-nordic:before,.fa-skiing-nordic:before{content:"\f7ca"}.fa-calendar-plus:before{content:"\f271"}.fa-plane-arrival:before{content:"\f5af"}.fa-arrow-alt-circle-left:before,.fa-circle-left:before{content:"\f359"}.fa-subway:before,.fa-train-subway:before{content:"\f239"}.fa-chart-gantt:before{content:"\e0e4"}.fa-indian-rupee-sign:before,.fa-indian-rupee:before,.fa-inr:before{content:"\e1bc"}.fa-crop-alt:before,.fa-crop-simple:before{content:"\f565"}.fa-money-bill-1:before,.fa-money-bill-alt:before{content:"\f3d1"}.fa-left-long:before,.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-dna:before{content:"\f471"}.fa-virus-slash:before{content:"\e075"}.fa-minus:before,.fa-subtract:before{content:"\f068"}.fa-chess:before{content:"\f439"}.fa-arrow-left-long:before,.fa-long-arrow-left:before{content:"\f177"}.fa-plug-circle-check:before{content:"\e55c"}.fa-street-view:before{content:"\f21d"}.fa-franc-sign:before{content:"\e18f"}.fa-volume-off:before{content:"\f026"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before,.fa-hands-american-sign-language-interpreting:before,.fa-hands-asl-interpreting:before{content:"\f2a3"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-droplet-slash:before,.fa-tint-slash:before{content:"\f5c7"}.fa-mosque:before{content:"\f678"}.fa-mosquito:before{content:"\e52b"}.fa-star-of-david:before{content:"\f69a"}.fa-person-military-rifle:before{content:"\e54b"}.fa-cart-shopping:before,.fa-shopping-cart:before{content:"\f07a"}.fa-vials:before{content:"\f493"}.fa-plug-circle-plus:before{content:"\e55f"}.fa-place-of-worship:before{content:"\f67f"}.fa-grip-vertical:before{content:"\f58e"}.fa-arrow-turn-up:before,.fa-level-up:before{content:"\f148"}.fa-u:before{content:"\55"}.fa-square-root-alt:before,.fa-square-root-variable:before{content:"\f698"}.fa-clock-four:before,.fa-clock:before{content:"\f017"}.fa-backward-step:before,.fa-step-backward:before{content:"\f048"}.fa-pallet:before{content:"\f482"}.fa-faucet:before{content:"\e005"}.fa-baseball-bat-ball:before{content:"\f432"}.fa-s:before{content:"\53"}.fa-timeline:before{content:"\e29c"}.fa-keyboard:before{content:"\f11c"}.fa-caret-down:before{content:"\f0d7"}.fa-clinic-medical:before,.fa-house-chimney-medical:before{content:"\f7f2"}.fa-temperature-3:before,.fa-temperature-three-quarters:before,.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-mobile-android-alt:before,.fa-mobile-screen:before{content:"\f3cf"}.fa-plane-up:before{content:"\e22d"}.fa-piggy-bank:before{content:"\f4d3"}.fa-battery-3:before,.fa-battery-half:before{content:"\f242"}.fa-mountain-city:before{content:"\e52e"}.fa-coins:before{content:"\f51e"}.fa-khanda:before{content:"\f66d"}.fa-sliders-h:before,.fa-sliders:before{content:"\f1de"}.fa-folder-tree:before{content:"\f802"}.fa-network-wired:before{content:"\f6ff"}.fa-map-pin:before{content:"\f276"}.fa-hamsa:before{content:"\f665"}.fa-cent-sign:before{content:"\e3f5"}.fa-flask:before{content:"\f0c3"}.fa-person-pregnant:before{content:"\e31e"}.fa-wand-sparkles:before{content:"\f72b"}.fa-ellipsis-v:before,.fa-ellipsis-vertical:before{content:"\f142"}.fa-ticket:before{content:"\f145"}.fa-power-off:before{content:"\f011"}.fa-long-arrow-alt-right:before,.fa-right-long:before{content:"\f30b"}.fa-flag-usa:before{content:"\f74d"}.fa-laptop-file:before{content:"\e51d"}.fa-teletype:before,.fa-tty:before{content:"\f1e4"}.fa-diagram-next:before{content:"\e476"}.fa-person-rifle:before{content:"\e54e"}.fa-house-medical-circle-exclamation:before{content:"\e512"}.fa-closed-captioning:before{content:"\f20a"}.fa-hiking:before,.fa-person-hiking:before{content:"\f6ec"}.fa-venus-double:before{content:"\f226"}.fa-images:before{content:"\f302"}.fa-calculator:before{content:"\f1ec"}.fa-people-pulling:before{content:"\e535"}.fa-n:before{content:"\4e"}.fa-cable-car:before,.fa-tram:before{content:"\f7da"}.fa-cloud-rain:before{content:"\f73d"}.fa-building-circle-xmark:before{content:"\e4d4"}.fa-ship:before{content:"\f21a"}.fa-arrows-down-to-line:before{content:"\e4b8"}.fa-download:before{content:"\f019"}.fa-face-grin:before,.fa-grin:before{content:"\f580"}.fa-backspace:before,.fa-delete-left:before{content:"\f55a"}.fa-eye-dropper-empty:before,.fa-eye-dropper:before,.fa-eyedropper:before{content:"\f1fb"}.fa-file-circle-check:before{content:"\e5a0"}.fa-forward:before{content:"\f04e"}.fa-mobile-android:before,.fa-mobile-phone:before,.fa-mobile:before{content:"\f3ce"}.fa-face-meh:before,.fa-meh:before{content:"\f11a"}.fa-align-center:before{content:"\f037"}.fa-book-dead:before,.fa-book-skull:before{content:"\f6b7"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-heart-circle-exclamation:before{content:"\e4fe"}.fa-home-alt:before,.fa-home-lg-alt:before,.fa-home:before,.fa-house:before{content:"\f015"}.fa-calendar-week:before{content:"\f784"}.fa-laptop-medical:before{content:"\f812"}.fa-b:before{content:"\42"}.fa-file-medical:before{content:"\f477"}.fa-dice-one:before{content:"\f525"}.fa-kiwi-bird:before{content:"\f535"}.fa-arrow-right-arrow-left:before,.fa-exchange:before{content:"\f0ec"}.fa-redo-alt:before,.fa-rotate-forward:before,.fa-rotate-right:before{content:"\f2f9"}.fa-cutlery:before,.fa-utensils:before{content:"\f2e7"}.fa-arrow-up-wide-short:before,.fa-sort-amount-up:before{content:"\f161"}.fa-mill-sign:before{content:"\e1ed"}.fa-bowl-rice:before{content:"\e2eb"}.fa-skull:before{content:"\f54c"}.fa-broadcast-tower:before,.fa-tower-broadcast:before{content:"\f519"}.fa-truck-pickup:before{content:"\f63c"}.fa-long-arrow-alt-up:before,.fa-up-long:before{content:"\f30c"}.fa-stop:before{content:"\f04d"}.fa-code-merge:before{content:"\f387"}.fa-upload:before{content:"\f093"}.fa-hurricane:before{content:"\f751"}.fa-mound:before{content:"\e52d"}.fa-toilet-portable:before{content:"\e583"}.fa-compact-disc:before{content:"\f51f"}.fa-file-arrow-down:before,.fa-file-download:before{content:"\f56d"}.fa-caravan:before{content:"\f8ff"}.fa-shield-cat:before{content:"\e572"}.fa-bolt:before,.fa-zap:before{content:"\f0e7"}.fa-glass-water:before{content:"\e4f4"}.fa-oil-well:before{content:"\e532"}.fa-vault:before{content:"\e2c5"}.fa-mars:before{content:"\f222"}.fa-toilet:before{content:"\f7d8"}.fa-plane-circle-xmark:before{content:"\e557"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen-sign:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble-sign:before,.fa-ruble:before{content:"\f158"}.fa-sun:before{content:"\f185"}.fa-guitar:before{content:"\f7a6"}.fa-face-laugh-wink:before,.fa-laugh-wink:before{content:"\f59c"}.fa-horse-head:before{content:"\f7ab"}.fa-bore-hole:before{content:"\e4c3"}.fa-industry:before{content:"\f275"}.fa-arrow-alt-circle-down:before,.fa-circle-down:before{content:"\f358"}.fa-arrows-turn-to-dots:before{content:"\e4c1"}.fa-florin-sign:before{content:"\e184"}.fa-arrow-down-short-wide:before,.fa-sort-amount-desc:before,.fa-sort-amount-down-alt:before{content:"\f884"}.fa-less-than:before{content:"\3c"}.fa-angle-down:before{content:"\f107"}.fa-car-tunnel:before{content:"\e4de"}.fa-head-side-cough:before{content:"\e061"}.fa-grip-lines:before{content:"\f7a4"}.fa-thumbs-down:before{content:"\f165"}.fa-user-lock:before{content:"\f502"}.fa-arrow-right-long:before,.fa-long-arrow-right:before{content:"\f178"}.fa-anchor-circle-xmark:before{content:"\e4ac"}.fa-ellipsis-h:before,.fa-ellipsis:before{content:"\f141"}.fa-chess-pawn:before{content:"\f443"}.fa-first-aid:before,.fa-kit-medical:before{content:"\f479"}.fa-person-through-window:before{content:"\e5a9"}.fa-toolbox:before{content:"\f552"}.fa-hands-holding-circle:before{content:"\e4fb"}.fa-bug:before{content:"\f188"}.fa-credit-card-alt:before,.fa-credit-card:before{content:"\f09d"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-hand-holding-hand:before{content:"\e4f7"}.fa-book-open-reader:before,.fa-book-reader:before{content:"\f5da"}.fa-mountain-sun:before{content:"\e52f"}.fa-arrows-left-right-to-line:before{content:"\e4ba"}.fa-dice-d20:before{content:"\f6cf"}.fa-truck-droplet:before{content:"\e58c"}.fa-file-circle-xmark:before{content:"\e5a1"}.fa-temperature-arrow-up:before,.fa-temperature-up:before{content:"\e040"}.fa-medal:before{content:"\f5a2"}.fa-bed:before{content:"\f236"}.fa-h-square:before,.fa-square-h:before{content:"\f0fd"}.fa-podcast:before{content:"\f2ce"}.fa-temperature-4:before,.fa-temperature-full:before,.fa-thermometer-4:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-bell:before{content:"\f0f3"}.fa-superscript:before{content:"\f12b"}.fa-plug-circle-xmark:before{content:"\e560"}.fa-star-of-life:before{content:"\f621"}.fa-phone-slash:before{content:"\f3dd"}.fa-paint-roller:before{content:"\f5aa"}.fa-hands-helping:before,.fa-handshake-angle:before{content:"\f4c4"}.fa-location-dot:before,.fa-map-marker-alt:before{content:"\f3c5"}.fa-file:before{content:"\f15b"}.fa-greater-than:before{content:"\3e"}.fa-person-swimming:before,.fa-swimmer:before{content:"\f5c4"}.fa-arrow-down:before{content:"\f063"}.fa-droplet:before,.fa-tint:before{content:"\f043"}.fa-eraser:before{content:"\f12d"}.fa-earth-america:before,.fa-earth-americas:before,.fa-earth:before,.fa-globe-americas:before{content:"\f57d"}.fa-person-burst:before{content:"\e53b"}.fa-dove:before{content:"\f4ba"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-socks:before{content:"\f696"}.fa-inbox:before{content:"\f01c"}.fa-section:before{content:"\e447"}.fa-gauge-high:before,.fa-tachometer-alt-fast:before,.fa-tachometer-alt:before{content:"\f625"}.fa-envelope-open-text:before{content:"\f658"}.fa-hospital-alt:before,.fa-hospital-wide:before,.fa-hospital:before{content:"\f0f8"}.fa-wine-bottle:before{content:"\f72f"}.fa-chess-rook:before{content:"\f447"}.fa-bars-staggered:before,.fa-reorder:before,.fa-stream:before{content:"\f550"}.fa-dharmachakra:before{content:"\f655"}.fa-hotdog:before{content:"\f80f"}.fa-blind:before,.fa-person-walking-with-cane:before{content:"\f29d"}.fa-drum:before{content:"\f569"}.fa-ice-cream:before{content:"\f810"}.fa-heart-circle-bolt:before{content:"\e4fc"}.fa-fax:before{content:"\f1ac"}.fa-paragraph:before{content:"\f1dd"}.fa-check-to-slot:before,.fa-vote-yea:before{content:"\f772"}.fa-star-half:before{content:"\f089"}.fa-boxes-alt:before,.fa-boxes-stacked:before,.fa-boxes:before{content:"\f468"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-assistive-listening-systems:before,.fa-ear-listen:before{content:"\f2a2"}.fa-tree-city:before{content:"\e587"}.fa-play:before{content:"\f04b"}.fa-font:before{content:"\f031"}.fa-rupiah-sign:before{content:"\e23d"}.fa-magnifying-glass:before,.fa-search:before{content:"\f002"}.fa-ping-pong-paddle-ball:before,.fa-table-tennis-paddle-ball:before,.fa-table-tennis:before{content:"\f45d"}.fa-diagnoses:before,.fa-person-dots-from-line:before{content:"\f470"}.fa-trash-can-arrow-up:before,.fa-trash-restore-alt:before{content:"\f82a"}.fa-naira-sign:before{content:"\e1f6"}.fa-cart-arrow-down:before{content:"\f218"}.fa-walkie-talkie:before{content:"\f8ef"}.fa-file-edit:before,.fa-file-pen:before{content:"\f31c"}.fa-receipt:before{content:"\f543"}.fa-pen-square:before,.fa-pencil-square:before,.fa-square-pen:before{content:"\f14b"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-person-circle-exclamation:before{content:"\e53f"}.fa-chevron-down:before{content:"\f078"}.fa-battery-5:before,.fa-battery-full:before,.fa-battery:before{content:"\f240"}.fa-skull-crossbones:before{content:"\f714"}.fa-code-compare:before{content:"\e13a"}.fa-list-dots:before,.fa-list-ul:before{content:"\f0ca"}.fa-school-lock:before{content:"\e56f"}.fa-tower-cell:before{content:"\e585"}.fa-down-long:before,.fa-long-arrow-alt-down:before{content:"\f309"}.fa-ranking-star:before{content:"\e561"}.fa-chess-king:before{content:"\f43f"}.fa-person-harassing:before{content:"\e549"}.fa-brazilian-real-sign:before{content:"\e46c"}.fa-landmark-alt:before,.fa-landmark-dome:before{content:"\f752"}.fa-arrow-up:before{content:"\f062"}.fa-television:before,.fa-tv-alt:before,.fa-tv:before{content:"\f26c"}.fa-shrimp:before{content:"\e448"}.fa-list-check:before,.fa-tasks:before{content:"\f0ae"}.fa-jug-detergent:before{content:"\e519"}.fa-circle-user:before,.fa-user-circle:before{content:"\f2bd"}.fa-user-shield:before{content:"\f505"}.fa-wind:before{content:"\f72e"}.fa-car-burst:before,.fa-car-crash:before{content:"\f5e1"}.fa-y:before{content:"\59"}.fa-person-snowboarding:before,.fa-snowboarding:before{content:"\f7ce"}.fa-shipping-fast:before,.fa-truck-fast:before{content:"\f48b"}.fa-fish:before{content:"\f578"}.fa-user-graduate:before{content:"\f501"}.fa-adjust:before,.fa-circle-half-stroke:before{content:"\f042"}.fa-clapperboard:before{content:"\e131"}.fa-circle-radiation:before,.fa-radiation-alt:before{content:"\f7ba"}.fa-baseball-ball:before,.fa-baseball:before{content:"\f433"}.fa-jet-fighter-up:before{content:"\e518"}.fa-diagram-project:before,.fa-project-diagram:before{content:"\f542"}.fa-copy:before{content:"\f0c5"}.fa-volume-mute:before,.fa-volume-times:before,.fa-volume-xmark:before{content:"\f6a9"}.fa-hand-sparkles:before{content:"\e05d"}.fa-grip-horizontal:before,.fa-grip:before{content:"\f58d"}.fa-share-from-square:before,.fa-share-square:before{content:"\f14d"}.fa-child-combatant:before,.fa-child-rifle:before{content:"\e4e0"}.fa-gun:before{content:"\e19b"}.fa-phone-square:before,.fa-square-phone:before{content:"\f098"}.fa-add:before,.fa-plus:before{content:"\2b"}.fa-expand:before{content:"\f065"}.fa-computer:before{content:"\e4e5"}.fa-close:before,.fa-multiply:before,.fa-remove:before,.fa-times:before,.fa-xmark:before{content:"\f00d"}.fa-arrows-up-down-left-right:before,.fa-arrows:before{content:"\f047"}.fa-chalkboard-teacher:before,.fa-chalkboard-user:before{content:"\f51c"}.fa-peso-sign:before{content:"\e222"}.fa-building-shield:before{content:"\e4d8"}.fa-baby:before{content:"\f77c"}.fa-users-line:before{content:"\e592"}.fa-quote-left-alt:before,.fa-quote-left:before{content:"\f10d"}.fa-tractor:before{content:"\f722"}.fa-trash-arrow-up:before,.fa-trash-restore:before{content:"\f829"}.fa-arrow-down-up-lock:before{content:"\e4b0"}.fa-lines-leaning:before{content:"\e51e"}.fa-ruler-combined:before{content:"\f546"}.fa-copyright:before{content:"\f1f9"}.fa-equals:before{content:"\3d"}.fa-blender:before{content:"\f517"}.fa-teeth:before{content:"\f62e"}.fa-ils:before,.fa-shekel-sign:before,.fa-shekel:before,.fa-sheqel-sign:before,.fa-sheqel:before{content:"\f20b"}.fa-map:before{content:"\f279"}.fa-rocket:before{content:"\f135"}.fa-photo-film:before,.fa-photo-video:before{content:"\f87c"}.fa-folder-minus:before{content:"\f65d"}.fa-store:before{content:"\f54e"}.fa-arrow-trend-up:before{content:"\e098"}.fa-plug-circle-minus:before{content:"\e55e"}.fa-sign-hanging:before,.fa-sign:before{content:"\f4d9"}.fa-bezier-curve:before{content:"\f55b"}.fa-bell-slash:before{content:"\f1f6"}.fa-tablet-android:before,.fa-tablet:before{content:"\f3fb"}.fa-school-flag:before{content:"\e56e"}.fa-fill:before{content:"\f575"}.fa-angle-up:before{content:"\f106"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-holly-berry:before{content:"\f7aa"}.fa-chevron-left:before{content:"\f053"}.fa-bacteria:before{content:"\e059"}.fa-hand-lizard:before{content:"\f258"}.fa-notdef:before{content:"\e1fe"}.fa-disease:before{content:"\f7fa"}.fa-briefcase-medical:before{content:"\f469"}.fa-genderless:before{content:"\f22d"}.fa-chevron-right:before{content:"\f054"}.fa-retweet:before{content:"\f079"}.fa-car-alt:before,.fa-car-rear:before{content:"\f5de"}.fa-pump-soap:before{content:"\e06b"}.fa-video-slash:before{content:"\f4e2"}.fa-battery-2:before,.fa-battery-quarter:before{content:"\f243"}.fa-radio:before{content:"\f8d7"}.fa-baby-carriage:before,.fa-carriage-baby:before{content:"\f77d"}.fa-traffic-light:before{content:"\f637"}.fa-thermometer:before{content:"\f491"}.fa-vr-cardboard:before{content:"\f729"}.fa-hand-middle-finger:before{content:"\f806"}.fa-percent:before,.fa-percentage:before{content:"\25"}.fa-truck-moving:before{content:"\f4df"}.fa-glass-water-droplet:before{content:"\e4f5"}.fa-display:before{content:"\e163"}.fa-face-smile:before,.fa-smile:before{content:"\f118"}.fa-thumb-tack:before,.fa-thumbtack:before{content:"\f08d"}.fa-trophy:before{content:"\f091"}.fa-person-praying:before,.fa-pray:before{content:"\f683"}.fa-hammer:before{content:"\f6e3"}.fa-hand-peace:before{content:"\f25b"}.fa-rotate:before,.fa-sync-alt:before{content:"\f2f1"}.fa-spinner:before{content:"\f110"}.fa-robot:before{content:"\f544"}.fa-peace:before{content:"\f67c"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-warehouse:before{content:"\f494"}.fa-arrow-up-right-dots:before{content:"\e4b7"}.fa-splotch:before{content:"\f5bc"}.fa-face-grin-hearts:before,.fa-grin-hearts:before{content:"\f584"}.fa-dice-four:before{content:"\f524"}.fa-sim-card:before{content:"\f7c4"}.fa-transgender-alt:before,.fa-transgender:before{content:"\f225"}.fa-mercury:before{content:"\f223"}.fa-arrow-turn-down:before,.fa-level-down:before{content:"\f149"}.fa-person-falling-burst:before{content:"\e547"}.fa-award:before{content:"\f559"}.fa-ticket-alt:before,.fa-ticket-simple:before{content:"\f3ff"}.fa-building:before{content:"\f1ad"}.fa-angle-double-left:before,.fa-angles-left:before{content:"\f100"}.fa-qrcode:before{content:"\f029"}.fa-clock-rotate-left:before,.fa-history:before{content:"\f1da"}.fa-face-grin-beam-sweat:before,.fa-grin-beam-sweat:before{content:"\f583"}.fa-arrow-right-from-file:before,.fa-file-export:before{content:"\f56e"}.fa-shield-blank:before,.fa-shield:before{content:"\f132"}.fa-arrow-up-short-wide:before,.fa-sort-amount-up-alt:before{content:"\f885"}.fa-house-medical:before{content:"\e3b2"}.fa-golf-ball-tee:before,.fa-golf-ball:before{content:"\f450"}.fa-chevron-circle-left:before,.fa-circle-chevron-left:before{content:"\f137"}.fa-house-chimney-window:before{content:"\e00d"}.fa-pen-nib:before{content:"\f5ad"}.fa-tent-arrow-turn-left:before{content:"\e580"}.fa-tents:before{content:"\e582"}.fa-magic:before,.fa-wand-magic:before{content:"\f0d0"}.fa-dog:before{content:"\f6d3"}.fa-carrot:before{content:"\f787"}.fa-moon:before{content:"\f186"}.fa-wine-glass-alt:before,.fa-wine-glass-empty:before{content:"\f5ce"}.fa-cheese:before{content:"\f7ef"}.fa-yin-yang:before{content:"\f6ad"}.fa-music:before{content:"\f001"}.fa-code-commit:before{content:"\f386"}.fa-temperature-low:before{content:"\f76b"}.fa-biking:before,.fa-person-biking:before{content:"\f84a"}.fa-broom:before{content:"\f51a"}.fa-shield-heart:before{content:"\e574"}.fa-gopuram:before{content:"\f664"}.fa-earth-oceania:before,.fa-globe-oceania:before{content:"\e47b"}.fa-square-xmark:before,.fa-times-square:before,.fa-xmark-square:before{content:"\f2d3"}.fa-hashtag:before{content:"\23"}.fa-expand-alt:before,.fa-up-right-and-down-left-from-center:before{content:"\f424"}.fa-oil-can:before{content:"\f613"}.fa-t:before{content:"\54"}.fa-hippo:before{content:"\f6ed"}.fa-chart-column:before{content:"\e0e3"}.fa-infinity:before{content:"\f534"}.fa-vial-circle-check:before{content:"\e596"}.fa-person-arrow-down-to-line:before{content:"\e538"}.fa-voicemail:before{content:"\f897"}.fa-fan:before{content:"\f863"}.fa-person-walking-luggage:before{content:"\e554"}.fa-arrows-alt-v:before,.fa-up-down:before{content:"\f338"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-calendar:before{content:"\f133"}.fa-trailer:before{content:"\e041"}.fa-bahai:before,.fa-haykal:before{content:"\f666"}.fa-sd-card:before{content:"\f7c2"}.fa-dragon:before{content:"\f6d5"}.fa-shoe-prints:before{content:"\f54b"}.fa-circle-plus:before,.fa-plus-circle:before{content:"\f055"}.fa-face-grin-tongue-wink:before,.fa-grin-tongue-wink:before{content:"\f58b"}.fa-hand-holding:before{content:"\f4bd"}.fa-plug-circle-exclamation:before{content:"\e55d"}.fa-chain-broken:before,.fa-chain-slash:before,.fa-link-slash:before,.fa-unlink:before{content:"\f127"}.fa-clone:before{content:"\f24d"}.fa-person-walking-arrow-loop-left:before{content:"\e551"}.fa-arrow-up-z-a:before,.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-fire-alt:before,.fa-fire-flame-curved:before{content:"\f7e4"}.fa-tornado:before{content:"\f76f"}.fa-file-circle-plus:before{content:"\e494"}.fa-book-quran:before,.fa-quran:before{content:"\f687"}.fa-anchor:before{content:"\f13d"}.fa-border-all:before{content:"\f84c"}.fa-angry:before,.fa-face-angry:before{content:"\f556"}.fa-cookie-bite:before{content:"\f564"}.fa-arrow-trend-down:before{content:"\e097"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-draw-polygon:before{content:"\f5ee"}.fa-balance-scale:before,.fa-scale-balanced:before{content:"\f24e"}.fa-gauge-simple-high:before,.fa-tachometer-fast:before,.fa-tachometer:before{content:"\f62a"}.fa-shower:before{content:"\f2cc"}.fa-desktop-alt:before,.fa-desktop:before{content:"\f390"}.fa-m:before{content:"\4d"}.fa-table-list:before,.fa-th-list:before{content:"\f00b"}.fa-comment-sms:before,.fa-sms:before{content:"\f7cd"}.fa-book:before{content:"\f02d"}.fa-user-plus:before{content:"\f234"}.fa-check:before{content:"\f00c"}.fa-battery-4:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-house-circle-check:before{content:"\e509"}.fa-angle-left:before{content:"\f104"}.fa-diagram-successor:before{content:"\e47a"}.fa-truck-arrow-right:before{content:"\e58b"}.fa-arrows-split-up-and-left:before{content:"\e4bc"}.fa-fist-raised:before,.fa-hand-fist:before{content:"\f6de"}.fa-cloud-moon:before{content:"\f6c3"}.fa-briefcase:before{content:"\f0b1"}.fa-person-falling:before{content:"\e546"}.fa-image-portrait:before,.fa-portrait:before{content:"\f3e0"}.fa-user-tag:before{content:"\f507"}.fa-rug:before{content:"\e569"}.fa-earth-europe:before,.fa-globe-europe:before{content:"\f7a2"}.fa-cart-flatbed-suitcase:before,.fa-luggage-cart:before{content:"\f59d"}.fa-rectangle-times:before,.fa-rectangle-xmark:before,.fa-times-rectangle:before,.fa-window-close:before{content:"\f410"}.fa-baht-sign:before{content:"\e0ac"}.fa-book-open:before{content:"\f518"}.fa-book-journal-whills:before,.fa-journal-whills:before{content:"\f66a"}.fa-handcuffs:before{content:"\e4f8"}.fa-exclamation-triangle:before,.fa-triangle-exclamation:before,.fa-warning:before{content:"\f071"}.fa-database:before{content:"\f1c0"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-bottle-droplet:before{content:"\e4c4"}.fa-mask-face:before{content:"\e1d7"}.fa-hill-rockslide:before{content:"\e508"}.fa-exchange-alt:before,.fa-right-left:before{content:"\f362"}.fa-paper-plane:before{content:"\f1d8"}.fa-road-circle-exclamation:before{content:"\e565"}.fa-dungeon:before{content:"\f6d9"}.fa-align-right:before{content:"\f038"}.fa-money-bill-1-wave:before,.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-life-ring:before{content:"\f1cd"}.fa-hands:before,.fa-sign-language:before,.fa-signing:before{content:"\f2a7"}.fa-calendar-day:before{content:"\f783"}.fa-ladder-water:before,.fa-swimming-pool:before,.fa-water-ladder:before{content:"\f5c5"}.fa-arrows-up-down:before,.fa-arrows-v:before{content:"\f07d"}.fa-face-grimace:before,.fa-grimace:before{content:"\f57f"}.fa-wheelchair-alt:before,.fa-wheelchair-move:before{content:"\e2ce"}.fa-level-down-alt:before,.fa-turn-down:before{content:"\f3be"}.fa-person-walking-arrow-right:before{content:"\e552"}.fa-envelope-square:before,.fa-square-envelope:before{content:"\f199"}.fa-dice:before{content:"\f522"}.fa-bowling-ball:before{content:"\f436"}.fa-brain:before{content:"\f5dc"}.fa-band-aid:before,.fa-bandage:before{content:"\f462"}.fa-calendar-minus:before{content:"\f272"}.fa-circle-xmark:before,.fa-times-circle:before,.fa-xmark-circle:before{content:"\f057"}.fa-gifts:before{content:"\f79c"}.fa-hotel:before{content:"\f594"}.fa-earth-asia:before,.fa-globe-asia:before{content:"\f57e"}.fa-id-card-alt:before,.fa-id-card-clip:before{content:"\f47f"}.fa-magnifying-glass-plus:before,.fa-search-plus:before{content:"\f00e"}.fa-thumbs-up:before{content:"\f164"}.fa-user-clock:before{content:"\f4fd"}.fa-allergies:before,.fa-hand-dots:before{content:"\f461"}.fa-file-invoice:before{content:"\f570"}.fa-window-minimize:before{content:"\f2d1"}.fa-coffee:before,.fa-mug-saucer:before{content:"\f0f4"}.fa-brush:before{content:"\f55d"}.fa-mask:before{content:"\f6fa"}.fa-magnifying-glass-minus:before,.fa-search-minus:before{content:"\f010"}.fa-ruler-vertical:before{content:"\f548"}.fa-user-alt:before,.fa-user-large:before{content:"\f406"}.fa-train-tram:before{content:"\e5b4"}.fa-user-nurse:before{content:"\f82f"}.fa-syringe:before{content:"\f48e"}.fa-cloud-sun:before{content:"\f6c4"}.fa-stopwatch-20:before{content:"\e06f"}.fa-square-full:before{content:"\f45c"}.fa-magnet:before{content:"\f076"}.fa-jar:before{content:"\e516"}.fa-note-sticky:before,.fa-sticky-note:before{content:"\f249"}.fa-bug-slash:before{content:"\e490"}.fa-arrow-up-from-water-pump:before{content:"\e4b6"}.fa-bone:before{content:"\f5d7"}.fa-user-injured:before{content:"\f728"}.fa-face-sad-tear:before,.fa-sad-tear:before{content:"\f5b4"}.fa-plane:before{content:"\f072"}.fa-tent-arrows-down:before{content:"\e581"}.fa-exclamation:before{content:"\21"}.fa-arrows-spin:before{content:"\e4bb"}.fa-print:before{content:"\f02f"}.fa-try:before,.fa-turkish-lira-sign:before,.fa-turkish-lira:before{content:"\e2bb"}.fa-dollar-sign:before,.fa-dollar:before,.fa-usd:before{content:"\24"}.fa-x:before{content:"\58"}.fa-magnifying-glass-dollar:before,.fa-search-dollar:before{content:"\f688"}.fa-users-cog:before,.fa-users-gear:before{content:"\f509"}.fa-person-military-pointing:before{content:"\e54a"}.fa-bank:before,.fa-building-columns:before,.fa-institution:before,.fa-museum:before,.fa-university:before{content:"\f19c"}.fa-umbrella:before{content:"\f0e9"}.fa-trowel:before{content:"\e589"}.fa-d:before{content:"\44"}.fa-stapler:before{content:"\e5af"}.fa-masks-theater:before,.fa-theater-masks:before{content:"\f630"}.fa-kip-sign:before{content:"\e1c4"}.fa-hand-point-left:before{content:"\f0a5"}.fa-handshake-alt:before,.fa-handshake-simple:before{content:"\f4c6"}.fa-fighter-jet:before,.fa-jet-fighter:before{content:"\f0fb"}.fa-share-alt-square:before,.fa-square-share-nodes:before{content:"\f1e1"}.fa-barcode:before{content:"\f02a"}.fa-plus-minus:before{content:"\e43c"}.fa-video-camera:before,.fa-video:before{content:"\f03d"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-person-circle-check:before{content:"\e53e"}.fa-level-up-alt:before,.fa-turn-up:before{content:"\f3bf"} +.fa-sr-only,.fa-sr-only-focusable:not(:focus),.sr-only,.sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}:host,:root{--fa-style-family-brands:"Font Awesome 6 Brands";--fa-font-brands:normal 400 1em/1 "Font Awesome 6 Brands"}@font-face{font-family:"Font Awesome 6 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}.fa-brands,.fab{font-weight:400}.fa-monero:before{content:"\f3d0"}.fa-hooli:before{content:"\f427"}.fa-yelp:before{content:"\f1e9"}.fa-cc-visa:before{content:"\f1f0"}.fa-lastfm:before{content:"\f202"}.fa-shopware:before{content:"\f5b5"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-aws:before{content:"\f375"}.fa-redhat:before{content:"\f7bc"}.fa-yoast:before{content:"\f2b1"}.fa-cloudflare:before{content:"\e07d"}.fa-ups:before{content:"\f7e0"}.fa-pixiv:before{content:"\e640"}.fa-wpexplorer:before{content:"\f2de"}.fa-dyalog:before{content:"\f399"}.fa-bity:before{content:"\f37a"}.fa-stackpath:before{content:"\f842"}.fa-buysellads:before{content:"\f20d"}.fa-first-order:before{content:"\f2b0"}.fa-modx:before{content:"\f285"}.fa-guilded:before{content:"\e07e"}.fa-vnv:before{content:"\f40b"}.fa-js-square:before,.fa-square-js:before{content:"\f3b9"}.fa-microsoft:before{content:"\f3ca"}.fa-qq:before{content:"\f1d6"}.fa-orcid:before{content:"\f8d2"}.fa-java:before{content:"\f4e4"}.fa-invision:before{content:"\f7b0"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-centercode:before{content:"\f380"}.fa-glide-g:before{content:"\f2a6"}.fa-drupal:before{content:"\f1a9"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-unity:before{content:"\e049"}.fa-whmcs:before{content:"\f40d"}.fa-rocketchat:before{content:"\f3e8"}.fa-vk:before{content:"\f189"}.fa-untappd:before{content:"\f405"}.fa-mailchimp:before{content:"\f59e"}.fa-css3-alt:before{content:"\f38b"}.fa-reddit-square:before,.fa-square-reddit:before{content:"\f1a2"}.fa-vimeo-v:before{content:"\f27d"}.fa-contao:before{content:"\f26d"}.fa-square-font-awesome:before{content:"\e5ad"}.fa-deskpro:before{content:"\f38f"}.fa-brave:before{content:"\e63c"}.fa-sistrix:before{content:"\f3ee"}.fa-instagram-square:before,.fa-square-instagram:before{content:"\e055"}.fa-battle-net:before{content:"\f835"}.fa-the-red-yeti:before{content:"\f69d"}.fa-hacker-news-square:before,.fa-square-hacker-news:before{content:"\f3af"}.fa-edge:before{content:"\f282"}.fa-threads:before{content:"\e618"}.fa-napster:before{content:"\f3d2"}.fa-snapchat-square:before,.fa-square-snapchat:before{content:"\f2ad"}.fa-google-plus-g:before{content:"\f0d5"}.fa-artstation:before{content:"\f77a"}.fa-markdown:before{content:"\f60f"}.fa-sourcetree:before{content:"\f7d3"}.fa-google-plus:before{content:"\f2b3"}.fa-diaspora:before{content:"\f791"}.fa-foursquare:before{content:"\f180"}.fa-stack-overflow:before{content:"\f16c"}.fa-github-alt:before{content:"\f113"}.fa-phoenix-squadron:before{content:"\f511"}.fa-pagelines:before{content:"\f18c"}.fa-algolia:before{content:"\f36c"}.fa-red-river:before{content:"\f3e3"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-safari:before{content:"\f267"}.fa-google:before{content:"\f1a0"}.fa-font-awesome-alt:before,.fa-square-font-awesome-stroke:before{content:"\f35c"}.fa-atlassian:before{content:"\f77b"}.fa-linkedin-in:before{content:"\f0e1"}.fa-digital-ocean:before{content:"\f391"}.fa-nimblr:before{content:"\f5a8"}.fa-chromecast:before{content:"\f838"}.fa-evernote:before{content:"\f839"}.fa-hacker-news:before{content:"\f1d4"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-adversal:before{content:"\f36a"}.fa-creative-commons:before{content:"\f25e"}.fa-watchman-monitoring:before{content:"\e087"}.fa-fonticons:before{content:"\f280"}.fa-weixin:before{content:"\f1d7"}.fa-shirtsinbulk:before{content:"\f214"}.fa-codepen:before{content:"\f1cb"}.fa-git-alt:before{content:"\f841"}.fa-lyft:before{content:"\f3c3"}.fa-rev:before{content:"\f5b2"}.fa-windows:before{content:"\f17a"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-square-viadeo:before,.fa-viadeo-square:before{content:"\f2aa"}.fa-meetup:before{content:"\f2e0"}.fa-centos:before{content:"\f789"}.fa-adn:before{content:"\f170"}.fa-cloudsmith:before{content:"\f384"}.fa-opensuse:before{content:"\e62b"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-dribbble-square:before,.fa-square-dribbble:before{content:"\f397"}.fa-codiepie:before{content:"\f284"}.fa-node:before{content:"\f419"}.fa-mix:before{content:"\f3cb"}.fa-steam:before{content:"\f1b6"}.fa-cc-apple-pay:before{content:"\f416"}.fa-scribd:before{content:"\f28a"}.fa-debian:before{content:"\e60b"}.fa-openid:before{content:"\f19b"}.fa-instalod:before{content:"\e081"}.fa-expeditedssl:before{content:"\f23e"}.fa-sellcast:before{content:"\f2da"}.fa-square-twitter:before,.fa-twitter-square:before{content:"\f081"}.fa-r-project:before{content:"\f4f7"}.fa-delicious:before{content:"\f1a5"}.fa-freebsd:before{content:"\f3a4"}.fa-vuejs:before{content:"\f41f"}.fa-accusoft:before{content:"\f369"}.fa-ioxhost:before{content:"\f208"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-app-store:before{content:"\f36f"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-itunes-note:before{content:"\f3b5"}.fa-golang:before{content:"\e40f"}.fa-kickstarter:before{content:"\f3bb"}.fa-grav:before{content:"\f2d6"}.fa-weibo:before{content:"\f18a"}.fa-uncharted:before{content:"\e084"}.fa-firstdraft:before{content:"\f3a1"}.fa-square-youtube:before,.fa-youtube-square:before{content:"\f431"}.fa-wikipedia-w:before{content:"\f266"}.fa-rendact:before,.fa-wpressr:before{content:"\f3e4"}.fa-angellist:before{content:"\f209"}.fa-galactic-republic:before{content:"\f50c"}.fa-nfc-directional:before{content:"\e530"}.fa-skype:before{content:"\f17e"}.fa-joget:before{content:"\f3b7"}.fa-fedora:before{content:"\f798"}.fa-stripe-s:before{content:"\f42a"}.fa-meta:before{content:"\e49b"}.fa-laravel:before{content:"\f3bd"}.fa-hotjar:before{content:"\f3b1"}.fa-bluetooth-b:before{content:"\f294"}.fa-square-letterboxd:before{content:"\e62e"}.fa-sticker-mule:before{content:"\f3f7"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-hips:before{content:"\f452"}.fa-behance:before{content:"\f1b4"}.fa-reddit:before{content:"\f1a1"}.fa-discord:before{content:"\f392"}.fa-chrome:before{content:"\f268"}.fa-app-store-ios:before{content:"\f370"}.fa-cc-discover:before{content:"\f1f2"}.fa-wpbeginner:before{content:"\f297"}.fa-confluence:before{content:"\f78d"}.fa-shoelace:before{content:"\e60c"}.fa-mdb:before{content:"\f8ca"}.fa-dochub:before{content:"\f394"}.fa-accessible-icon:before{content:"\f368"}.fa-ebay:before{content:"\f4f4"}.fa-amazon:before{content:"\f270"}.fa-unsplash:before{content:"\e07c"}.fa-yarn:before{content:"\f7e3"}.fa-square-steam:before,.fa-steam-square:before{content:"\f1b7"}.fa-500px:before{content:"\f26e"}.fa-square-vimeo:before,.fa-vimeo-square:before{content:"\f194"}.fa-asymmetrik:before{content:"\f372"}.fa-font-awesome-flag:before,.fa-font-awesome-logo-full:before,.fa-font-awesome:before{content:"\f2b4"}.fa-gratipay:before{content:"\f184"}.fa-apple:before{content:"\f179"}.fa-hive:before{content:"\e07f"}.fa-gitkraken:before{content:"\f3a6"}.fa-keybase:before{content:"\f4f5"}.fa-apple-pay:before{content:"\f415"}.fa-padlet:before{content:"\e4a0"}.fa-amazon-pay:before{content:"\f42c"}.fa-github-square:before,.fa-square-github:before{content:"\f092"}.fa-stumbleupon:before{content:"\f1a4"}.fa-fedex:before{content:"\f797"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-shopify:before{content:"\e057"}.fa-neos:before{content:"\f612"}.fa-square-threads:before{content:"\e619"}.fa-hackerrank:before{content:"\f5f7"}.fa-researchgate:before{content:"\f4f8"}.fa-swift:before{content:"\f8e1"}.fa-angular:before{content:"\f420"}.fa-speakap:before{content:"\f3f3"}.fa-angrycreative:before{content:"\f36e"}.fa-y-combinator:before{content:"\f23b"}.fa-empire:before{content:"\f1d1"}.fa-envira:before{content:"\f299"}.fa-google-scholar:before{content:"\e63b"}.fa-gitlab-square:before,.fa-square-gitlab:before{content:"\e5ae"}.fa-studiovinari:before{content:"\f3f8"}.fa-pied-piper:before{content:"\f2ae"}.fa-wordpress:before{content:"\f19a"}.fa-product-hunt:before{content:"\f288"}.fa-firefox:before{content:"\f269"}.fa-linode:before{content:"\f2b8"}.fa-goodreads:before{content:"\f3a8"}.fa-odnoklassniki-square:before,.fa-square-odnoklassniki:before{content:"\f264"}.fa-jsfiddle:before{content:"\f1cc"}.fa-sith:before{content:"\f512"}.fa-themeisle:before{content:"\f2b2"}.fa-page4:before{content:"\f3d7"}.fa-hashnode:before{content:"\e499"}.fa-react:before{content:"\f41b"}.fa-cc-paypal:before{content:"\f1f4"}.fa-squarespace:before{content:"\f5be"}.fa-cc-stripe:before{content:"\f1f5"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-bitcoin:before{content:"\f379"}.fa-keycdn:before{content:"\f3ba"}.fa-opera:before{content:"\f26a"}.fa-itch-io:before{content:"\f83a"}.fa-umbraco:before{content:"\f8e8"}.fa-galactic-senate:before{content:"\f50d"}.fa-ubuntu:before{content:"\f7df"}.fa-draft2digital:before{content:"\f396"}.fa-stripe:before{content:"\f429"}.fa-houzz:before{content:"\f27c"}.fa-gg:before{content:"\f260"}.fa-dhl:before{content:"\f790"}.fa-pinterest-square:before,.fa-square-pinterest:before{content:"\f0d3"}.fa-xing:before{content:"\f168"}.fa-blackberry:before{content:"\f37b"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-playstation:before{content:"\f3df"}.fa-quinscape:before{content:"\f459"}.fa-less:before{content:"\f41d"}.fa-blogger-b:before{content:"\f37d"}.fa-opencart:before{content:"\f23d"}.fa-vine:before{content:"\f1ca"}.fa-signal-messenger:before{content:"\e663"}.fa-paypal:before{content:"\f1ed"}.fa-gitlab:before{content:"\f296"}.fa-typo3:before{content:"\f42b"}.fa-reddit-alien:before{content:"\f281"}.fa-yahoo:before{content:"\f19e"}.fa-dailymotion:before{content:"\e052"}.fa-affiliatetheme:before{content:"\f36b"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-bootstrap:before{content:"\f836"}.fa-odnoklassniki:before{content:"\f263"}.fa-nfc-symbol:before{content:"\e531"}.fa-mintbit:before{content:"\e62f"}.fa-ethereum:before{content:"\f42e"}.fa-speaker-deck:before{content:"\f83c"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-patreon:before{content:"\f3d9"}.fa-avianex:before{content:"\f374"}.fa-ello:before{content:"\f5f1"}.fa-gofore:before{content:"\f3a7"}.fa-bimobject:before{content:"\f378"}.fa-brave-reverse:before{content:"\e63d"}.fa-facebook-f:before{content:"\f39e"}.fa-google-plus-square:before,.fa-square-google-plus:before{content:"\f0d4"}.fa-mandalorian:before{content:"\f50f"}.fa-first-order-alt:before{content:"\f50a"}.fa-osi:before{content:"\f41a"}.fa-google-wallet:before{content:"\f1ee"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-periscope:before{content:"\f3da"}.fa-fulcrum:before{content:"\f50b"}.fa-cloudscale:before{content:"\f383"}.fa-forumbee:before{content:"\f211"}.fa-mizuni:before{content:"\f3cc"}.fa-schlix:before{content:"\f3ea"}.fa-square-xing:before,.fa-xing-square:before{content:"\f169"}.fa-bandcamp:before{content:"\f2d5"}.fa-wpforms:before{content:"\f298"}.fa-cloudversify:before{content:"\f385"}.fa-usps:before{content:"\f7e1"}.fa-megaport:before{content:"\f5a3"}.fa-magento:before{content:"\f3c4"}.fa-spotify:before{content:"\f1bc"}.fa-optin-monster:before{content:"\f23c"}.fa-fly:before{content:"\f417"}.fa-aviato:before{content:"\f421"}.fa-itunes:before{content:"\f3b4"}.fa-cuttlefish:before{content:"\f38c"}.fa-blogger:before{content:"\f37c"}.fa-flickr:before{content:"\f16e"}.fa-viber:before{content:"\f409"}.fa-soundcloud:before{content:"\f1be"}.fa-digg:before{content:"\f1a6"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-letterboxd:before{content:"\e62d"}.fa-symfony:before{content:"\f83d"}.fa-maxcdn:before{content:"\f136"}.fa-etsy:before{content:"\f2d7"}.fa-facebook-messenger:before{content:"\f39f"}.fa-audible:before{content:"\f373"}.fa-think-peaks:before{content:"\f731"}.fa-bilibili:before{content:"\e3d9"}.fa-erlang:before{content:"\f39d"}.fa-x-twitter:before{content:"\e61b"}.fa-cotton-bureau:before{content:"\f89e"}.fa-dashcube:before{content:"\f210"}.fa-42-group:before,.fa-innosoft:before{content:"\e080"}.fa-stack-exchange:before{content:"\f18d"}.fa-elementor:before{content:"\f430"}.fa-pied-piper-square:before,.fa-square-pied-piper:before{content:"\e01e"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-palfed:before{content:"\f3d8"}.fa-superpowers:before{content:"\f2dd"}.fa-resolving:before{content:"\f3e7"}.fa-xbox:before{content:"\f412"}.fa-searchengin:before{content:"\f3eb"}.fa-tiktok:before{content:"\e07b"}.fa-facebook-square:before,.fa-square-facebook:before{content:"\f082"}.fa-renren:before{content:"\f18b"}.fa-linux:before{content:"\f17c"}.fa-glide:before{content:"\f2a5"}.fa-linkedin:before{content:"\f08c"}.fa-hubspot:before{content:"\f3b2"}.fa-deploydog:before{content:"\f38e"}.fa-twitch:before{content:"\f1e8"}.fa-ravelry:before{content:"\f2d9"}.fa-mixer:before{content:"\e056"}.fa-lastfm-square:before,.fa-square-lastfm:before{content:"\f203"}.fa-vimeo:before{content:"\f40a"}.fa-mendeley:before{content:"\f7b3"}.fa-uniregistry:before{content:"\f404"}.fa-figma:before{content:"\f799"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-dropbox:before{content:"\f16b"}.fa-instagram:before{content:"\f16d"}.fa-cmplid:before{content:"\e360"}.fa-upwork:before{content:"\e641"}.fa-facebook:before{content:"\f09a"}.fa-gripfire:before{content:"\f3ac"}.fa-jedi-order:before{content:"\f50e"}.fa-uikit:before{content:"\f403"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-phabricator:before{content:"\f3db"}.fa-ussunnah:before{content:"\f407"}.fa-earlybirds:before{content:"\f39a"}.fa-trade-federation:before{content:"\f513"}.fa-autoprefixer:before{content:"\f41c"}.fa-whatsapp:before{content:"\f232"}.fa-slideshare:before{content:"\f1e7"}.fa-google-play:before{content:"\f3ab"}.fa-viadeo:before{content:"\f2a9"}.fa-line:before{content:"\f3c0"}.fa-google-drive:before{content:"\f3aa"}.fa-servicestack:before{content:"\f3ec"}.fa-simplybuilt:before{content:"\f215"}.fa-bitbucket:before{content:"\f171"}.fa-imdb:before{content:"\f2d8"}.fa-deezer:before{content:"\e077"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-jira:before{content:"\f7b1"}.fa-docker:before{content:"\f395"}.fa-screenpal:before{content:"\e570"}.fa-bluetooth:before{content:"\f293"}.fa-gitter:before{content:"\f426"}.fa-d-and-d:before{content:"\f38d"}.fa-microblog:before{content:"\e01a"}.fa-cc-diners-club:before{content:"\f24c"}.fa-gg-circle:before{content:"\f261"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-yandex:before{content:"\f413"}.fa-readme:before{content:"\f4d5"}.fa-html5:before{content:"\f13b"}.fa-sellsy:before{content:"\f213"}.fa-sass:before{content:"\f41e"}.fa-wirsindhandwerk:before,.fa-wsh:before{content:"\e2d0"}.fa-buromobelexperte:before{content:"\f37f"}.fa-salesforce:before{content:"\f83b"}.fa-octopus-deploy:before{content:"\e082"}.fa-medapps:before{content:"\f3c6"}.fa-ns8:before{content:"\f3d5"}.fa-pinterest-p:before{content:"\f231"}.fa-apper:before{content:"\f371"}.fa-fort-awesome:before{content:"\f286"}.fa-waze:before{content:"\f83f"}.fa-cc-jcb:before{content:"\f24b"}.fa-snapchat-ghost:before,.fa-snapchat:before{content:"\f2ab"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-rust:before{content:"\e07a"}.fa-wix:before{content:"\f5cf"}.fa-behance-square:before,.fa-square-behance:before{content:"\f1b5"}.fa-supple:before{content:"\f3f9"}.fa-webflow:before{content:"\e65c"}.fa-rebel:before{content:"\f1d0"}.fa-css3:before{content:"\f13c"}.fa-staylinked:before{content:"\f3f5"}.fa-kaggle:before{content:"\f5fa"}.fa-space-awesome:before{content:"\e5ac"}.fa-deviantart:before{content:"\f1bd"}.fa-cpanel:before{content:"\f388"}.fa-goodreads-g:before{content:"\f3a9"}.fa-git-square:before,.fa-square-git:before{content:"\f1d2"}.fa-square-tumblr:before,.fa-tumblr-square:before{content:"\f174"}.fa-trello:before{content:"\f181"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-get-pocket:before{content:"\f265"}.fa-perbyte:before{content:"\e083"}.fa-grunt:before{content:"\f3ad"}.fa-weebly:before{content:"\f5cc"}.fa-connectdevelop:before{content:"\f20e"}.fa-leanpub:before{content:"\f212"}.fa-black-tie:before{content:"\f27e"}.fa-themeco:before{content:"\f5c6"}.fa-python:before{content:"\f3e2"}.fa-android:before{content:"\f17b"}.fa-bots:before{content:"\e340"}.fa-free-code-camp:before{content:"\f2c5"}.fa-hornbill:before{content:"\f592"}.fa-js:before{content:"\f3b8"}.fa-ideal:before{content:"\e013"}.fa-git:before{content:"\f1d3"}.fa-dev:before{content:"\f6cc"}.fa-sketch:before{content:"\f7c6"}.fa-yandex-international:before{content:"\f414"}.fa-cc-amex:before{content:"\f1f3"}.fa-uber:before{content:"\f402"}.fa-github:before{content:"\f09b"}.fa-php:before{content:"\f457"}.fa-alipay:before{content:"\f642"}.fa-youtube:before{content:"\f167"}.fa-skyatlas:before{content:"\f216"}.fa-firefox-browser:before{content:"\e007"}.fa-replyd:before{content:"\f3e6"}.fa-suse:before{content:"\f7d6"}.fa-jenkins:before{content:"\f3b6"}.fa-twitter:before{content:"\f099"}.fa-rockrms:before{content:"\f3e9"}.fa-pinterest:before{content:"\f0d2"}.fa-buffer:before{content:"\f837"}.fa-npm:before{content:"\f3d4"}.fa-yammer:before{content:"\f840"}.fa-btc:before{content:"\f15a"}.fa-dribbble:before{content:"\f17d"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-internet-explorer:before{content:"\f26b"}.fa-stubber:before{content:"\e5c7"}.fa-telegram-plane:before,.fa-telegram:before{content:"\f2c6"}.fa-old-republic:before{content:"\f510"}.fa-odysee:before{content:"\e5c6"}.fa-square-whatsapp:before,.fa-whatsapp-square:before{content:"\f40c"}.fa-node-js:before{content:"\f3d3"}.fa-edge-legacy:before{content:"\e078"}.fa-slack-hash:before,.fa-slack:before{content:"\f198"}.fa-medrt:before{content:"\f3c8"}.fa-usb:before{content:"\f287"}.fa-tumblr:before{content:"\f173"}.fa-vaadin:before{content:"\f408"}.fa-quora:before{content:"\f2c4"}.fa-square-x-twitter:before{content:"\e61a"}.fa-reacteurope:before{content:"\f75d"}.fa-medium-m:before,.fa-medium:before{content:"\f23a"}.fa-amilia:before{content:"\f36d"}.fa-mixcloud:before{content:"\f289"}.fa-flipboard:before{content:"\f44d"}.fa-viacoin:before{content:"\f237"}.fa-critical-role:before{content:"\f6c9"}.fa-sitrox:before{content:"\e44a"}.fa-discourse:before{content:"\f393"}.fa-joomla:before{content:"\f1aa"}.fa-mastodon:before{content:"\f4f6"}.fa-airbnb:before{content:"\f834"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-buy-n-large:before{content:"\f8a6"}.fa-gulp:before{content:"\f3ae"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-strava:before{content:"\f428"}.fa-ember:before{content:"\f423"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-teamspeak:before{content:"\f4f9"}.fa-pushed:before{content:"\f3e1"}.fa-wordpress-simple:before{content:"\f411"}.fa-nutritionix:before{content:"\f3d6"}.fa-wodu:before{content:"\e088"}.fa-google-pay:before{content:"\e079"}.fa-intercom:before{content:"\f7af"}.fa-zhihu:before{content:"\f63f"}.fa-korvue:before{content:"\f42f"}.fa-pix:before{content:"\e43a"}.fa-steam-symbol:before{content:"\f3f6"}:host,:root{--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}.fa-regular,.far{font-weight:400}:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900}@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f27a} \ No newline at end of file diff --git a/assets/fontawesome/webfonts/fa-brands-400.woff2 b/assets/fontawesome/webfonts/fa-brands-400.woff2 new file mode 100644 index 0000000..36fbda7 Binary files /dev/null and b/assets/fontawesome/webfonts/fa-brands-400.woff2 differ diff --git a/assets/fontawesome/webfonts/fa-regular-400.woff2 b/assets/fontawesome/webfonts/fa-regular-400.woff2 new file mode 100644 index 0000000..b6cabba Binary files /dev/null and b/assets/fontawesome/webfonts/fa-regular-400.woff2 differ diff --git a/assets/fontawesome/webfonts/fa-solid-900.woff2 b/assets/fontawesome/webfonts/fa-solid-900.woff2 new file mode 100644 index 0000000..824d518 Binary files /dev/null and b/assets/fontawesome/webfonts/fa-solid-900.woff2 differ diff --git a/assets/fonts/inter/inter.css b/assets/fonts/inter/inter.css new file mode 100644 index 0000000..9bb529b --- /dev/null +++ b/assets/fonts/inter/inter.css @@ -0,0 +1,36 @@ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v19/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuOKfMZg.ttf) format('truetype'); +} +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v19/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfMZg.ttf) format('truetype'); +} +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v19/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuI6fMZg.ttf) format('truetype'); +} +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v19/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuGKYMZg.ttf) format('truetype'); +} +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/inter/v19/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuFuYMZg.ttf) format('truetype'); +} + diff --git a/assets/tailwind.css b/assets/tailwind.css new file mode 100644 index 0000000..a135c34 --- /dev/null +++ b/assets/tailwind.css @@ -0,0 +1 @@ +/*! tailwindcss v3.4.10 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-size:1em;font-variation-settings:normal}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-feature-settings:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.-left-2{left:-.5rem}.-right-1{right:-.25rem}.-top-1{top:-.25rem}.-top-10{top:-2.5rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-2{bottom:.5rem}.bottom-4{bottom:1rem}.bottom-6{bottom:1.5rem}.left-0{left:0}.left-1\/2{left:50%}.left-2{left:.5rem}.left-4{left:1rem}.right-0{right:0}.right-2{right:.5rem}.right-3{right:.75rem}.right-4{right:1rem}.right-6{right:1.5rem}.right-\[-100px\]{right:-100px}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:1rem}.z-10{z-index:10}.z-40{z-index:40}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mr-4{margin-right:1rem}.mr-auto{margin-right:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-20{margin-top:5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1{height:.25rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-28{height:7rem}.h-3{height:.75rem}.h-4{height:1rem}.h-48{height:12rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-full{height:100%}.max-h-\[80vh\]{max-height:80vh}.max-h-\[90vh\]{max-height:90vh}.min-h-\[300px\]{min-height:300px}.min-h-\[72px\]{min-height:72px}.min-h-\[calc\(100vh-104px\)\]{min-height:calc(100vh - 104px)}.min-h-screen{min-height:100vh}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-28{width:7rem}.w-3{width:.75rem}.w-4{width:1rem}.w-48{width:12rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-full{width:100%}.min-w-\[160px\]{min-width:160px}.min-w-\[240px\]{min-width:240px}.max-w-2xl{max-width:42rem}.max-w-32{max-width:8rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.translate-x-full{--tw-translate-x:100%}.translate-x-full,.translate-y-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-full{--tw-translate-y:100%}.rotate-180{--tw-rotate:180deg}.rotate-180,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.75rem*var(--tw-space-x-reverse))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse));margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2rem*var(--tw-space-y-reverse));margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.scroll-smooth{scroll-behavior:smooth}.whitespace-nowrap{white-space:nowrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity))}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity))}.border-blue-500\/20{border-color:rgba(59,130,246,.2)}.border-blue-500\/30{border-color:rgba(59,130,246,.3)}.border-blue-700\/30{border-color:rgba(29,78,216,.3)}.border-blue-700\/50{border-color:rgba(29,78,216,.5)}.border-cyan-500\/20{border-color:rgba(6,182,212,.2)}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-500\/10{border-color:hsla(220,9%,46%,.1)}.border-gray-500\/20{border-color:hsla(220,9%,46%,.2)}.border-gray-500\/30{border-color:hsla(220,9%,46%,.3)}.border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.border-gray-600\/30{border-color:rgba(75,85,99,.3)}.border-gray-700\/30{border-color:rgba(55,65,81,.3)}.border-green-200{--tw-border-opacity:1;border-color:rgb(187 247 208/var(--tw-border-opacity))}.border-green-300{--tw-border-opacity:1;border-color:rgb(134 239 172/var(--tw-border-opacity))}.border-green-500\/20{border-color:rgba(34,197,94,.2)}.border-green-500\/30{border-color:rgba(34,197,94,.3)}.border-orange-500{--tw-border-opacity:1;border-color:rgb(249 115 22/var(--tw-border-opacity))}.border-orange-500\/10{border-color:rgba(249,115,22,.1)}.border-orange-500\/20{border-color:rgba(249,115,22,.2)}.border-orange-500\/30{border-color:rgba(249,115,22,.3)}.border-purple-500\/20{border-color:rgba(168,85,247,.2)}.border-red-300{--tw-border-opacity:1;border-color:rgb(252 165 165/var(--tw-border-opacity))}.border-red-500\/20{border-color:rgba(239,68,68,.2)}.border-yellow-200{--tw-border-opacity:1;border-color:rgb(254 240 138/var(--tw-border-opacity))}.border-yellow-500\/20{border-color:rgba(234,179,8,.2)}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-black\/30{background-color:rgba(0,0,0,.3)}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-black\/80{background-color:rgba(0,0,0,.8)}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity))}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(96 165 250/var(--tw-bg-opacity))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity))}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-blue-500\/20{background-color:rgba(59,130,246,.2)}.bg-blue-500\/90{background-color:rgba(59,130,246,.9)}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity))}.bg-blue-900\/20{background-color:rgba(30,58,138,.2)}.bg-cyan-500\/10{background-color:rgba(6,182,212,.1)}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-500{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity))}.bg-gray-500\/10{background-color:hsla(220,9%,46%,.1)}.bg-gray-500\/20{background-color:hsla(220,9%,46%,.2)}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}.bg-gray-600\/80{background-color:rgba(75,85,99,.8)}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.bg-gray-700\/50{background-color:rgba(55,65,81,.5)}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-gray-800\/50{background-color:rgba(31,41,55,.5)}.bg-gray-800\/95{background-color:rgba(31,41,55,.95)}.bg-gray-900\/30{background-color:rgba(17,24,39,.3)}.bg-green-100{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity))}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(187 247 208/var(--tw-bg-opacity))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(74 222 128/var(--tw-bg-opacity))}.bg-green-400\/20{background-color:rgba(74,222,128,.2)}.bg-green-50{--tw-bg-opacity:1;background-color:rgb(240 253 244/var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity))}.bg-green-500\/10{background-color:rgba(34,197,94,.1)}.bg-green-500\/20{background-color:rgba(34,197,94,.2)}.bg-green-500\/90{background-color:rgba(34,197,94,.9)}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(22 163 74/var(--tw-bg-opacity))}.bg-orange-400{--tw-bg-opacity:1;background-color:rgb(251 146 60/var(--tw-bg-opacity))}.bg-orange-500{--tw-bg-opacity:1;background-color:rgb(249 115 22/var(--tw-bg-opacity))}.bg-orange-500\/10{background-color:rgba(249,115,22,.1)}.bg-orange-500\/15{background-color:rgba(249,115,22,.15)}.bg-orange-500\/20{background-color:rgba(249,115,22,.2)}.bg-orange-500\/5{background-color:rgba(249,115,22,.05)}.bg-orange-600{--tw-bg-opacity:1;background-color:rgb(234 88 12/var(--tw-bg-opacity))}.bg-purple-500\/10{background-color:rgba(168,85,247,.1)}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(254 202 202/var(--tw-bg-opacity))}.bg-red-400{--tw-bg-opacity:1;background-color:rgb(248 113 113/var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity))}.bg-red-500\/10{background-color:rgba(239,68,68,.1)}.bg-red-500\/20{background-color:rgba(239,68,68,.2)}.bg-red-500\/90{background-color:rgba(239,68,68,.9)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-white\/20{background-color:hsla(0,0%,100%,.2)}.bg-yellow-400{--tw-bg-opacity:1;background-color:rgb(250 204 21/var(--tw-bg-opacity))}.bg-yellow-50{--tw-bg-opacity:1;background-color:rgb(254 252 232/var(--tw-bg-opacity))}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity))}.bg-yellow-500\/10{background-color:rgba(234,179,8,.1)}.bg-yellow-500\/20{background-color:rgba(234,179,8,.2)}.bg-yellow-500\/90{background-color:rgba(234,179,8,.9)}.bg-opacity-50{--tw-bg-opacity:0.5}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-blue-900\/20{--tw-gradient-from:rgba(30,58,138,.2) var(--tw-gradient-from-position);--tw-gradient-to:rgba(30,58,138,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-gray-800\/20{--tw-gradient-from:rgba(31,41,55,.2) var(--tw-gradient-from-position);--tw-gradient-to:rgba(31,41,55,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-orange-500{--tw-gradient-from:#f97316 var(--tw-gradient-from-position);--tw-gradient-to:rgba(249,115,22,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-orange-500\/10{--tw-gradient-from:rgba(249,115,22,.1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(249,115,22,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-gray-900\/20{--tw-gradient-to:rgba(17,24,39,.2) var(--tw-gradient-to-position)}.to-orange-600{--tw-gradient-to:#ea580c var(--tw-gradient-to-position)}.to-purple-900\/20{--tw-gradient-to:rgba(88,28,135,.2) var(--tw-gradient-to-position)}.to-yellow-500\/10{--tw-gradient-to:rgba(234,179,8,.1) var(--tw-gradient-to-position)}.fill-blue-500{fill:#3b82f6}.fill-white{fill:#fff}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-1\.5{padding-bottom:.375rem;padding-top:.375rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-4{padding-bottom:1rem;padding-top:1rem}.pr-2{padding-right:.5rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-6xl{font-size:3.75rem;line-height:1}.text-\[300px\]{font-size:300px}.text-\[3rem\]{font-size:3rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.lowercase{text-transform:lowercase}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-blue-200{--tw-text-opacity:1;color:rgb(191 219 254/var(--tw-text-opacity))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity))}.text-blue-700{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity:1;color:rgb(30 64 175/var(--tw-text-opacity))}.text-cyan-300{--tw-text-opacity:1;color:rgb(103 232 249/var(--tw-text-opacity))}.text-cyan-400{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity))}.text-cyan-500{--tw-text-opacity:1;color:rgb(6 182 212/var(--tw-text-opacity))}.text-emerald-500{--tw-text-opacity:1;color:rgb(16 185 129/var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.text-green-300{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity))}.text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity))}.text-green-600{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity))}.text-green-700{--tw-text-opacity:1;color:rgb(21 128 61/var(--tw-text-opacity))}.text-green-800{--tw-text-opacity:1;color:rgb(22 101 52/var(--tw-text-opacity))}.text-orange-200{--tw-text-opacity:1;color:rgb(254 215 170/var(--tw-text-opacity))}.text-orange-300{--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity))}.text-purple-500{--tw-text-opacity:1;color:rgb(168 85 247/var(--tw-text-opacity))}.text-red-200{--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity))}.text-red-300{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-white\/10{color:hsla(0,0%,100%,.1)}.text-yellow-200{--tw-text-opacity:1;color:rgb(254 240 138/var(--tw-text-opacity))}.text-yellow-300{--tw-text-opacity:1;color:rgb(253 224 71/var(--tw-text-opacity))}.text-yellow-400{--tw-text-opacity:1;color:rgb(250 204 21/var(--tw-text-opacity))}.text-yellow-500{--tw-text-opacity:1;color:rgb(234 179 8/var(--tw-text-opacity))}.text-yellow-600{--tw-text-opacity:1;color:rgb(202 138 4/var(--tw-text-opacity))}.text-yellow-700{--tw-text-opacity:1;color:rgb(161 98 7/var(--tw-text-opacity))}.text-yellow-800{--tw-text-opacity:1;color:rgb(133 77 14/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.placeholder-gray-400::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}.placeholder-gray-400::placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}.placeholder-gray-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity))}.placeholder-gray-500::placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity))}.opacity-0{opacity:0}.opacity-10{opacity:.1}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-2xl,.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-orange-500\/30{--tw-ring-color:rgba(249,115,22,.3)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-md,.backdrop-blur-sm{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.transition-all{transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-opacity{transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.\[checksum\:4\]{checksum:4}.\[data\:variable\]{data:variable}.\[name\:4\]{name:4}.\[size\:4\]{size:4}.hover\:scale-125:hover{--tw-scale-x:1.25;--tw-scale-y:1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.hover\:border-orange-400:hover{--tw-border-opacity:1;border-color:rgb(251 146 60/var(--tw-border-opacity))}.hover\:bg-blue-200:hover{--tw-bg-opacity:1;background-color:rgb(191 219 254/var(--tw-bg-opacity))}.hover\:bg-blue-500:hover{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity))}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity))}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity))}.hover\:bg-emerald-600:hover{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity))}.hover\:bg-gray-500:hover{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity))}.hover\:bg-gray-500\/80:hover{background-color:hsla(220,9%,46%,.8)}.hover\:bg-gray-600:hover{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}.hover\:bg-gray-700:hover{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.hover\:bg-gray-700\/50:hover{background-color:rgba(55,65,81,.5)}.hover\:bg-gray-800\/30:hover{background-color:rgba(31,41,55,.3)}.hover\:bg-green-500:hover{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity))}.hover\:bg-green-500\/20:hover{background-color:rgba(34,197,94,.2)}.hover\:bg-green-500\/30:hover{background-color:rgba(34,197,94,.3)}.hover\:bg-green-600:hover{--tw-bg-opacity:1;background-color:rgb(22 163 74/var(--tw-bg-opacity))}.hover\:bg-orange-500:hover{--tw-bg-opacity:1;background-color:rgb(249 115 22/var(--tw-bg-opacity))}.hover\:bg-orange-500\/20:hover{background-color:rgba(249,115,22,.2)}.hover\:bg-orange-600:hover{--tw-bg-opacity:1;background-color:rgb(234 88 12/var(--tw-bg-opacity))}.hover\:bg-red-200:hover{--tw-bg-opacity:1;background-color:rgb(254 202 202/var(--tw-bg-opacity))}.hover\:bg-red-500\/20:hover{background-color:rgba(239,68,68,.2)}.hover\:bg-red-600:hover{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity))}.hover\:bg-white\/30:hover{background-color:hsla(0,0%,100%,.3)}.hover\:bg-yellow-500\/20:hover{background-color:rgba(234,179,8,.2)}.hover\:from-orange-600:hover{--tw-gradient-from:#ea580c var(--tw-gradient-from-position);--tw-gradient-to:rgba(234,88,12,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.hover\:to-orange-700:hover{--tw-gradient-to:#c2410c var(--tw-gradient-to-position)}.hover\:text-blue-300:hover{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity))}.hover\:text-gray-300:hover{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:text-green-300:hover{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity))}.hover\:text-orange-300:hover{--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.hover\:opacity-100:hover{opacity:1}.hover\:opacity-80:hover{opacity:.8}.focus\:border-green-500\/40:focus{border-color:rgba(34,197,94,.4)}.focus\:border-orange-500\/40:focus{border-color:rgba(249,115,22,.4)}.focus\:border-purple-500\/40:focus{border-color:rgba(168,85,247,.4)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-gray-400:disabled{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity))}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05}.group:hover .group-hover\:scale-105,.group:hover .group-hover\:scale-110{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width:640px){.sm\:mb-0{margin-bottom:0}.sm\:mb-3{margin-bottom:.75rem}.sm\:mr-2{margin-right:.5rem}.sm\:block{display:block}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:h-10{height:2.5rem}.sm\:h-12{height:3rem}.sm\:w-10{width:2.5rem}.sm\:w-12{width:3rem}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-4{gap:1rem}.sm\:space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.sm\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.75rem*var(--tw-space-x-reverse))}.sm\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.sm\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(0px*var(--tw-space-y-reverse));margin-top:calc(0px*(1 - var(--tw-space-y-reverse)))}.sm\:p-4{padding:1rem}.sm\:px-0{padding-left:0;padding-right:0}.sm\:px-3{padding-left:.75rem;padding-right:.75rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-1\.5{padding-bottom:.375rem;padding-top:.375rem}.sm\:text-base{font-size:1rem;line-height:1.5rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}.sm\:text-xl{font-size:1.25rem;line-height:1.75rem}}@media (min-width:768px){.md\:flex{display:flex}.md\:hidden{display:none}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width:1024px){.lg\:block{display:block}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:px-8{padding-left:2rem;padding-right:2rem}} \ No newline at end of file diff --git a/dist/app-boot.js b/dist/app-boot.js new file mode 100644 index 0000000..90fe11a --- /dev/null +++ b/dist/app-boot.js @@ -0,0 +1,18061 @@ +// src/crypto/EnhancedSecureCryptoUtils.js +var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils { + static _keyMetadata = /* @__PURE__ */ new WeakMap(); + // Initialize secure logging system after class definition + // Utility to sort object keys for deterministic serialization + static sortObjectKeys(obj) { + if (typeof obj !== "object" || obj === null) { + return obj; + } + if (Array.isArray(obj)) { + return obj.map(_EnhancedSecureCryptoUtils.sortObjectKeys); + } + const sortedObj = {}; + Object.keys(obj).sort().forEach((key) => { + sortedObj[key] = _EnhancedSecureCryptoUtils.sortObjectKeys(obj[key]); + }); + return sortedObj; + } + // Utility to assert CryptoKey type and properties + static assertCryptoKey(key, expectedName = null, expectedUsages = []) { + if (!(key instanceof CryptoKey)) throw new Error("Expected CryptoKey"); + if (expectedName && key.algorithm?.name !== expectedName) { + throw new Error(`Expected algorithm ${expectedName}, got ${key.algorithm?.name}`); + } + for (const u of expectedUsages) { + if (!key.usages || !key.usages.includes(u)) { + throw new Error(`Missing required key usage: ${u}`); + } + } + } + // Helper function to convert ArrayBuffer to Base64 + static arrayBufferToBase64(buffer) { + let binary = ""; + const bytes = new Uint8Array(buffer); + const len = bytes.byteLength; + for (let i = 0; i < len; i++) { + binary += String.fromCharCode(bytes[i]); + } + return btoa(binary); + } + // Helper function to convert Base64 to ArrayBuffer + static base64ToArrayBuffer(base64) { + try { + if (typeof base64 !== "string" || !base64) { + throw new Error("Invalid base64 input: must be a non-empty string"); + } + const cleanBase64 = base64.trim(); + if (!/^[A-Za-z0-9+/]*={0,2}$/.test(cleanBase64)) { + throw new Error("Invalid base64 format"); + } + if (cleanBase64 === "") { + return new ArrayBuffer(0); + } + const binaryString = atob(cleanBase64); + const len = binaryString.length; + const bytes = new Uint8Array(len); + for (let i = 0; i < len; i++) { + bytes[i] = binaryString.charCodeAt(i); + } + return bytes.buffer; + } catch (error) { + console.error("Base64 to ArrayBuffer conversion failed:", error.message); + throw new Error(`Base64 conversion error: ${error.message}`); + } + } + // Helper function to convert hex string to Uint8Array + static hexToUint8Array(hexString) { + try { + if (!hexString || typeof hexString !== "string") { + throw new Error("Invalid hex string input: must be a non-empty string"); + } + const cleanHex = hexString.replace(/:/g, "").replace(/\s/g, ""); + if (!/^[0-9a-fA-F]*$/.test(cleanHex)) { + throw new Error("Invalid hex format: contains non-hex characters"); + } + if (cleanHex.length % 2 !== 0) { + throw new Error("Invalid hex format: odd length"); + } + const bytes = new Uint8Array(cleanHex.length / 2); + for (let i = 0; i < cleanHex.length; i += 2) { + bytes[i / 2] = parseInt(cleanHex.substr(i, 2), 16); + } + return bytes; + } catch (error) { + console.error("Hex to Uint8Array conversion failed:", error.message); + throw new Error(`Hex conversion error: ${error.message}`); + } + } + static async encryptData(data, password) { + try { + const dataString = typeof data === "string" ? data : JSON.stringify(data); + const salt = crypto.getRandomValues(new Uint8Array(16)); + const encoder = new TextEncoder(); + const passwordBuffer = encoder.encode(password); + const keyMaterial = await crypto.subtle.importKey( + "raw", + passwordBuffer, + { name: "PBKDF2" }, + false, + ["deriveKey"] + ); + const key = await crypto.subtle.deriveKey( + { + name: "PBKDF2", + salt, + iterations: 1e5, + hash: "SHA-256" + }, + keyMaterial, + { name: "AES-GCM", length: 256 }, + false, + ["encrypt"] + ); + const iv = crypto.getRandomValues(new Uint8Array(12)); + const dataBuffer = encoder.encode(dataString); + const encrypted = await crypto.subtle.encrypt( + { name: "AES-GCM", iv }, + key, + dataBuffer + ); + const encryptedPackage = { + version: "1.0", + salt: Array.from(salt), + iv: Array.from(iv), + data: Array.from(new Uint8Array(encrypted)), + timestamp: Date.now() + }; + const packageString = JSON.stringify(encryptedPackage); + return _EnhancedSecureCryptoUtils.arrayBufferToBase64(new TextEncoder().encode(packageString).buffer); + } catch (error) { + console.error("Encryption failed:", error.message); + throw new Error(`Encryption error: ${error.message}`); + } + } + static async decryptData(encryptedData, password) { + try { + const packageBuffer = _EnhancedSecureCryptoUtils.base64ToArrayBuffer(encryptedData); + const packageString = new TextDecoder().decode(packageBuffer); + const encryptedPackage = JSON.parse(packageString); + if (!encryptedPackage.version || !encryptedPackage.salt || !encryptedPackage.iv || !encryptedPackage.data) { + throw new Error("Invalid encrypted data format"); + } + const salt = new Uint8Array(encryptedPackage.salt); + const iv = new Uint8Array(encryptedPackage.iv); + const encrypted = new Uint8Array(encryptedPackage.data); + const encoder = new TextEncoder(); + const passwordBuffer = encoder.encode(password); + const keyMaterial = await crypto.subtle.importKey( + "raw", + passwordBuffer, + { name: "PBKDF2" }, + false, + ["deriveKey"] + ); + const key = await crypto.subtle.deriveKey( + { + name: "PBKDF2", + salt, + iterations: 1e5, + hash: "SHA-256" + }, + keyMaterial, + { name: "AES-GCM", length: 256 }, + false, + ["decrypt"] + ); + const decrypted = await crypto.subtle.decrypt( + { name: "AES-GCM", iv }, + key, + encrypted + ); + const decryptedString = new TextDecoder().decode(decrypted); + try { + return JSON.parse(decryptedString); + } catch { + return decryptedString; + } + } catch (error) { + console.error("Decryption failed:", error.message); + throw new Error(`Decryption error: ${error.message}`); + } + } + // Generate secure password for data exchange + static generateSecurePassword() { + const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?"; + const length = 32; + const randomValues = new Uint32Array(length); + crypto.getRandomValues(randomValues); + let password = ""; + for (let i = 0; i < length; i++) { + password += chars[randomValues[i] % chars.length]; + } + return password; + } + // Real security level calculation with actual verification + static async calculateSecurityLevel(securityManager) { + let score = 0; + const maxScore = 100; + const verificationResults = {}; + try { + if (!securityManager || !securityManager.securityFeatures) { + console.warn("Security manager not fully initialized, using fallback calculation"); + return { + level: "INITIALIZING", + score: 0, + color: "gray", + verificationResults: {}, + timestamp: Date.now(), + details: "Security system initializing...", + isRealData: false + }; + } + const sessionType = securityManager.currentSessionType || "demo"; + const isDemoSession = sessionType === "demo"; + try { + if (await _EnhancedSecureCryptoUtils.verifyEncryption(securityManager)) { + score += 20; + verificationResults.encryption = { passed: true, details: "AES-GCM encryption verified", points: 20 }; + } else { + verificationResults.encryption = { passed: false, details: "Encryption not working", points: 0 }; + } + } catch (error) { + verificationResults.encryption = { passed: false, details: `Encryption check failed: ${error.message}`, points: 0 }; + } + try { + if (await _EnhancedSecureCryptoUtils.verifyECDHKeyExchange(securityManager)) { + score += 15; + verificationResults.keyExchange = { passed: true, details: "Simple key exchange verified", points: 15 }; + } else { + verificationResults.keyExchange = { passed: false, details: "Key exchange failed", points: 0 }; + } + } catch (error) { + verificationResults.keyExchange = { passed: false, details: `Key exchange check failed: ${error.message}`, points: 0 }; + } + if (await _EnhancedSecureCryptoUtils.verifyMessageIntegrity(securityManager)) { + score += 10; + verificationResults.messageIntegrity = { passed: true, details: "Message integrity verified", points: 10 }; + } else { + verificationResults.messageIntegrity = { passed: false, details: "Message integrity failed", points: 0 }; + } + if (await _EnhancedSecureCryptoUtils.verifyRateLimiting(securityManager)) { + score += 5; + verificationResults.rateLimiting = { passed: true, details: "Rate limiting active", points: 5 }; + } else { + verificationResults.rateLimiting = { passed: false, details: "Rate limiting not working", points: 0 }; + } + if (!isDemoSession && await _EnhancedSecureCryptoUtils.verifyECDSASignatures(securityManager)) { + score += 15; + verificationResults.ecdsa = { passed: true, details: "ECDSA signatures verified", points: 15 }; + } else { + const reason = isDemoSession ? "Enhanced session required - feature not available" : "ECDSA signatures failed"; + verificationResults.ecdsa = { passed: false, details: reason, points: 0 }; + } + if (!isDemoSession && await _EnhancedSecureCryptoUtils.verifyMetadataProtection(securityManager)) { + score += 10; + verificationResults.metadataProtection = { passed: true, details: "Metadata protection verified", points: 10 }; + } else { + const reason = isDemoSession ? "Enhanced session required - feature not available" : "Metadata protection failed"; + verificationResults.metadataProtection = { passed: false, details: reason, points: 0 }; + } + if (!isDemoSession && await _EnhancedSecureCryptoUtils.verifyPFS(securityManager)) { + score += 10; + verificationResults.pfs = { passed: true, details: "Perfect Forward Secrecy active", points: 10 }; + } else { + const reason = isDemoSession ? "Enhanced session required - feature not available" : "PFS not active"; + verificationResults.pfs = { passed: false, details: reason, points: 0 }; + } + if (!isDemoSession && await _EnhancedSecureCryptoUtils.verifyNestedEncryption(securityManager)) { + score += 5; + verificationResults.nestedEncryption = { passed: true, details: "Nested encryption active", points: 5 }; + } else { + const reason = isDemoSession ? "Enhanced session required - feature not available" : "Nested encryption failed"; + verificationResults.nestedEncryption = { passed: false, details: reason, points: 0 }; + } + if (!isDemoSession && await _EnhancedSecureCryptoUtils.verifyPacketPadding(securityManager)) { + score += 5; + verificationResults.packetPadding = { passed: true, details: "Packet padding active", points: 5 }; + } else { + const reason = isDemoSession ? "Enhanced session required - feature not available" : "Packet padding failed"; + verificationResults.packetPadding = { passed: false, details: reason, points: 0 }; + } + if (sessionType === "premium" && await _EnhancedSecureCryptoUtils.verifyAdvancedFeatures(securityManager)) { + score += 10; + verificationResults.advancedFeatures = { passed: true, details: "Advanced features active", points: 10 }; + } else { + const reason = sessionType === "demo" ? "Premium session required - feature not available" : sessionType === "basic" ? "Premium session required - feature not available" : "Advanced features failed"; + verificationResults.advancedFeatures = { passed: false, details: reason, points: 0 }; + } + const percentage = Math.round(score / maxScore * 100); + const availableChecks = isDemoSession ? 4 : 10; + const passedChecks = Object.values(verificationResults).filter((r) => r.passed).length; + const result = { + level: percentage >= 85 ? "HIGH" : percentage >= 65 ? "MEDIUM" : percentage >= 35 ? "LOW" : "CRITICAL", + score: percentage, + color: percentage >= 85 ? "green" : percentage >= 65 ? "orange" : percentage >= 35 ? "yellow" : "red", + verificationResults, + timestamp: Date.now(), + details: `Real verification: ${score}/${maxScore} security checks passed (${passedChecks}/${availableChecks} available)`, + isRealData: true, + passedChecks, + totalChecks: availableChecks, + sessionType, + maxPossibleScore: isDemoSession ? 50 : 100 + // Demo sessions can only get max 50 points (4 checks) + }; + console.log("Real security level calculated:", { + score: percentage, + level: result.level, + passedChecks, + totalChecks: availableChecks, + sessionType, + maxPossibleScore: result.maxPossibleScore + }); + return result; + } catch (error) { + console.error("Security level calculation failed:", error.message); + return { + level: "UNKNOWN", + score: 0, + color: "red", + verificationResults: {}, + timestamp: Date.now(), + details: `Verification failed: ${error.message}`, + isRealData: false + }; + } + } + // Real verification functions + static async verifyEncryption(securityManager) { + try { + if (!securityManager.encryptionKey) return false; + const testData = "Test encryption verification"; + const encoder = new TextEncoder(); + const testBuffer = encoder.encode(testData); + const iv = crypto.getRandomValues(new Uint8Array(12)); + const encrypted = await crypto.subtle.encrypt( + { name: "AES-GCM", iv }, + securityManager.encryptionKey, + testBuffer + ); + const decrypted = await crypto.subtle.decrypt( + { name: "AES-GCM", iv }, + securityManager.encryptionKey, + encrypted + ); + const decryptedText = new TextDecoder().decode(decrypted); + return decryptedText === testData; + } catch (error) { + console.error("Encryption verification failed:", error.message); + return false; + } + } + static async verifyECDHKeyExchange(securityManager) { + try { + if (!securityManager.ecdhKeyPair || !securityManager.ecdhKeyPair.privateKey || !securityManager.ecdhKeyPair.publicKey) { + return false; + } + const keyType = securityManager.ecdhKeyPair.privateKey.algorithm.name; + const curve = securityManager.ecdhKeyPair.privateKey.algorithm.namedCurve; + return keyType === "ECDH" && (curve === "P-384" || curve === "P-256"); + } catch (error) { + console.error("ECDH verification failed:", error.message); + return false; + } + } + static async verifyECDSASignatures(securityManager) { + try { + if (!securityManager.ecdsaKeyPair || !securityManager.ecdsaKeyPair.privateKey || !securityManager.ecdsaKeyPair.publicKey) { + return false; + } + const testData = "Test ECDSA signature verification"; + const encoder = new TextEncoder(); + const testBuffer = encoder.encode(testData); + const signature = await crypto.subtle.sign( + { name: "ECDSA", hash: "SHA-256" }, + securityManager.ecdsaKeyPair.privateKey, + testBuffer + ); + const isValid = await crypto.subtle.verify( + { name: "ECDSA", hash: "SHA-256" }, + securityManager.ecdsaKeyPair.publicKey, + signature, + testBuffer + ); + return isValid; + } catch (error) { + console.error("ECDSA verification failed:", error.message); + return false; + } + } + static async verifyMessageIntegrity(securityManager) { + try { + if (!securityManager.macKey || !(securityManager.macKey instanceof CryptoKey)) { + console.warn("MAC key not available or invalid for message integrity verification"); + return false; + } + const testData = "Test message integrity verification"; + const encoder = new TextEncoder(); + const testBuffer = encoder.encode(testData); + const hmac = await crypto.subtle.sign( + { name: "HMAC", hash: "SHA-256" }, + securityManager.macKey, + testBuffer + ); + const isValid = await crypto.subtle.verify( + { name: "HMAC", hash: "SHA-256" }, + securityManager.macKey, + hmac, + testBuffer + ); + return isValid; + } catch (error) { + console.error("Message integrity verification failed:", error.message); + return false; + } + } + static async verifyNestedEncryption(securityManager) { + try { + if (!securityManager.nestedEncryptionKey || !(securityManager.nestedEncryptionKey instanceof CryptoKey)) { + console.warn("Nested encryption key not available or invalid"); + return false; + } + const testData = "Test nested encryption verification"; + const encoder = new TextEncoder(); + const testBuffer = encoder.encode(testData); + const encrypted = await crypto.subtle.encrypt( + { name: "AES-GCM", iv: crypto.getRandomValues(new Uint8Array(12)) }, + securityManager.nestedEncryptionKey, + testBuffer + ); + return encrypted && encrypted.byteLength > 0; + } catch (error) { + console.error("Nested encryption verification failed:", error.message); + return false; + } + } + static async verifyPacketPadding(securityManager) { + try { + if (!securityManager.paddingConfig || !securityManager.paddingConfig.enabled) return false; + const testData = "Test packet padding verification"; + const encoder = new TextEncoder(); + const testBuffer = encoder.encode(testData); + const paddingSize = Math.floor(Math.random() * (securityManager.paddingConfig.maxPadding - securityManager.paddingConfig.minPadding)) + securityManager.paddingConfig.minPadding; + const paddedData = new Uint8Array(testBuffer.byteLength + paddingSize); + paddedData.set(new Uint8Array(testBuffer), 0); + return paddedData.byteLength >= testBuffer.byteLength + securityManager.paddingConfig.minPadding; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Packet padding verification failed", { error: error.message }); + return false; + } + } + static async verifyAdvancedFeatures(securityManager) { + try { + const hasFakeTraffic = securityManager.fakeTrafficConfig && securityManager.fakeTrafficConfig.enabled; + const hasDecoyChannels = securityManager.decoyChannelsConfig && securityManager.decoyChannelsConfig.enabled; + const hasAntiFingerprinting = securityManager.antiFingerprintingConfig && securityManager.antiFingerprintingConfig.enabled; + return hasFakeTraffic || hasDecoyChannels || hasAntiFingerprinting; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Advanced features verification failed", { error: error.message }); + return false; + } + } + static async verifyMutualAuth(securityManager) { + try { + if (!securityManager.isVerified || !securityManager.verificationCode) return false; + return securityManager.isVerified && securityManager.verificationCode.length > 0; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Mutual auth verification failed", { error: error.message }); + return false; + } + } + static async verifyMetadataProtection(securityManager) { + try { + if (!securityManager.metadataKey) return false; + const testData = "Test metadata protection verification"; + const encoder = new TextEncoder(); + const testBuffer = encoder.encode(testData); + const encrypted = await crypto.subtle.encrypt( + { name: "AES-GCM", iv: crypto.getRandomValues(new Uint8Array(12)) }, + securityManager.metadataKey, + testBuffer + ); + return encrypted && encrypted.byteLength > 0; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Metadata protection verification failed", { error: error.message }); + return false; + } + } + static async verifyReplayProtection(securityManager) { + try { + if (!securityManager.processedMessageIds || !securityManager.sequenceNumber) return false; + const testId = Date.now().toString(); + if (securityManager.processedMessageIds.has(testId)) return false; + securityManager.processedMessageIds.add(testId); + return true; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Replay protection verification failed", { error: error.message }); + return false; + } + } + static async verifyNonExtractableKeys(securityManager) { + try { + if (!securityManager.encryptionKey) return false; + const keyData = await crypto.subtle.exportKey("raw", securityManager.encryptionKey); + return keyData && keyData.byteLength > 0; + } catch (error) { + return true; + } + } + static async verifyEnhancedValidation(securityManager) { + try { + if (!securityManager.securityFeatures) return false; + const hasValidation = securityManager.securityFeatures.hasEnhancedValidation || securityManager.securityFeatures.hasEnhancedReplayProtection; + return hasValidation; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Enhanced validation verification failed", { error: error.message }); + return false; + } + } + static async verifyRateLimiting(securityManager) { + try { + const testId = "test_" + Date.now(); + const canProceed = await _EnhancedSecureCryptoUtils.rateLimiter.checkMessageRate(testId, 1, 6e4); + return securityManager.rateLimiterId && _EnhancedSecureCryptoUtils.rateLimiter && typeof _EnhancedSecureCryptoUtils.rateLimiter.checkMessageRate === "function" && canProceed === true; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Rate limiting verification failed", { error: error.message }); + return false; + } + } + static async verifyPFS(securityManager) { + try { + return securityManager.securityFeatures && securityManager.securityFeatures.hasPFS === true && securityManager.keyRotationInterval && securityManager.currentKeyVersion !== void 0 && securityManager.keyVersions && securityManager.keyVersions instanceof Map; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "PFS verification failed", { error: error.message }); + return false; + } + } + // Rate limiting implementation + static rateLimiter = { + messages: /* @__PURE__ */ new Map(), + connections: /* @__PURE__ */ new Map(), + locks: /* @__PURE__ */ new Map(), + async checkMessageRate(identifier, limit = 60, windowMs = 6e4) { + if (typeof identifier !== "string" || identifier.length > 256) { + return false; + } + const key = `msg_${identifier}`; + if (this.locks.has(key)) { + await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * 10) + 5)); + return this.checkMessageRate(identifier, limit, windowMs); + } + this.locks.set(key, true); + try { + const now = Date.now(); + if (!this.messages.has(key)) { + this.messages.set(key, []); + } + const timestamps = this.messages.get(key); + const validTimestamps = timestamps.filter((ts) => now - ts < windowMs); + if (validTimestamps.length >= limit) { + return false; + } + validTimestamps.push(now); + this.messages.set(key, validTimestamps); + return true; + } finally { + this.locks.delete(key); + } + }, + async checkConnectionRate(identifier, limit = 5, windowMs = 3e5) { + if (typeof identifier !== "string" || identifier.length > 256) { + return false; + } + const key = `conn_${identifier}`; + if (this.locks.has(key)) { + await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * 10) + 5)); + return this.checkConnectionRate(identifier, limit, windowMs); + } + this.locks.set(key, true); + try { + const now = Date.now(); + if (!this.connections.has(key)) { + this.connections.set(key, []); + } + const timestamps = this.connections.get(key); + const validTimestamps = timestamps.filter((ts) => now - ts < windowMs); + if (validTimestamps.length >= limit) { + return false; + } + validTimestamps.push(now); + this.connections.set(key, validTimestamps); + return true; + } finally { + this.locks.delete(key); + } + }, + cleanup() { + const now = Date.now(); + const maxAge = 36e5; + for (const [key, timestamps] of this.messages.entries()) { + if (this.locks.has(key)) continue; + const valid = timestamps.filter((ts) => now - ts < maxAge); + if (valid.length === 0) { + this.messages.delete(key); + } else { + this.messages.set(key, valid); + } + } + for (const [key, timestamps] of this.connections.entries()) { + if (this.locks.has(key)) continue; + const valid = timestamps.filter((ts) => now - ts < maxAge); + if (valid.length === 0) { + this.connections.delete(key); + } else { + this.connections.set(key, valid); + } + } + for (const lockKey of this.locks.keys()) { + const keyTimestamp = parseInt(lockKey.split("_").pop()) || 0; + if (now - keyTimestamp > 3e4) { + this.locks.delete(lockKey); + } + } + } + }; + static validateSalt(salt) { + if (!salt || salt.length !== 64) { + throw new Error("Salt must be exactly 64 bytes"); + } + const uniqueBytes = new Set(salt); + if (uniqueBytes.size < 16) { + throw new Error("Salt has insufficient entropy"); + } + return true; + } + // Secure logging without data leaks + static secureLog = { + logs: [], + maxLogs: 100, + isProductionMode: false, + // Initialize production mode detection + init() { + this.isProductionMode = this._detectProductionMode(); + if (this.isProductionMode) { + console.log("[SecureChat] Production mode detected - sensitive logging disabled"); + } + }, + _detectProductionMode() { + return typeof process !== "undefined" && false || !window.DEBUG_MODE && !window.DEVELOPMENT_MODE || window.location.hostname && !window.location.hostname.includes("localhost") && !window.location.hostname.includes("127.0.0.1") && !window.location.hostname.includes(".local") || typeof window.webpackHotUpdate === "undefined" && !window.location.search.includes("debug"); + }, + log(level, message, context = {}) { + const sanitizedContext = this.sanitizeContext(context); + const logEntry = { + timestamp: Date.now(), + level, + message, + context: sanitizedContext, + id: crypto.getRandomValues(new Uint32Array(1))[0] + }; + this.logs.push(logEntry); + if (this.logs.length > this.maxLogs) { + this.logs = this.logs.slice(-this.maxLogs); + } + if (this.isProductionMode) { + if (level === "error") { + console.error(`\u274C [SecureChat] ${message} [ERROR_CODE: ${this._generateErrorCode(message)}]`); + } else if (level === "warn") { + console.warn(`\u26A0\uFE0F [SecureChat] ${message}`); + } else { + return; + } + } else { + if (level === "error") { + console.error(`\u274C [SecureChat] ${message}`, { errorType: sanitizedContext?.constructor?.name || "Unknown" }); + } else if (level === "warn") { + console.warn(`\u26A0\uFE0F [SecureChat] ${message}`, { details: sanitizedContext }); + } else { + console.log(`[SecureChat] ${message}`, sanitizedContext); + } + } + }, + // Генерирует безопасный код ошибки для production + _generateErrorCode(message) { + const hash = message.split("").reduce((a, b) => { + a = (a << 5) - a + b.charCodeAt(0); + return a & a; + }, 0); + return Math.abs(hash).toString(36).substring(0, 6).toUpperCase(); + }, + sanitizeContext(context) { + if (!context || typeof context !== "object") { + return context; + } + const sensitivePatterns = [ + /key/i, + /secret/i, + /password/i, + /token/i, + /signature/i, + /challenge/i, + /proof/i, + /salt/i, + /iv/i, + /nonce/i, + /hash/i, + /fingerprint/i, + /mac/i, + /private/i, + /encryption/i, + /decryption/i + ]; + const sanitized = {}; + for (const [key, value] of Object.entries(context)) { + const isSensitive = sensitivePatterns.some( + (pattern) => pattern.test(key) || typeof value === "string" && pattern.test(value) + ); + if (isSensitive) { + sanitized[key] = "[REDACTED]"; + } else if (typeof value === "string" && value.length > 100) { + sanitized[key] = value.substring(0, 100) + "...[TRUNCATED]"; + } else if (value instanceof ArrayBuffer || value instanceof Uint8Array) { + sanitized[key] = `[${value.constructor.name}(${value.byteLength || value.length} bytes)]`; + } else if (value && typeof value === "object" && !Array.isArray(value)) { + sanitized[key] = this.sanitizeContext(value); + } else { + sanitized[key] = value; + } + } + return sanitized; + }, + getLogs(level = null) { + if (level) { + return this.logs.filter((log) => log.level === level); + } + return [...this.logs]; + }, + clearLogs() { + this.logs = []; + }, + // Метод для отправки ошибок на сервер в production + async sendErrorToServer(errorCode, message, context = {}) { + if (!this.isProductionMode) { + return; + } + try { + const safeErrorData = { + errorCode, + timestamp: Date.now(), + userAgent: navigator.userAgent.substring(0, 100), + url: window.location.href.substring(0, 100) + }; + if (window.DEBUG_MODE) { + console.log("[SecureChat] Error logged to server:", safeErrorData); + } + } catch (e) { + } + } + }; + // Generate ECDH key pair for secure key exchange (non-extractable) with fallback + static async generateECDHKeyPair() { + try { + try { + const keyPair = await crypto.subtle.generateKey( + { + name: "ECDH", + namedCurve: "P-384" + }, + false, + // Non-extractable for enhanced security + ["deriveKey"] + ); + _EnhancedSecureCryptoUtils.secureLog.log("info", "ECDH key pair generated successfully (P-384)", { + curve: "P-384", + extractable: false + }); + return keyPair; + } catch (p384Error) { + _EnhancedSecureCryptoUtils.secureLog.log("warn", "P-384 generation failed, trying P-256", { error: p384Error.message }); + const keyPair = await crypto.subtle.generateKey( + { + name: "ECDH", + namedCurve: "P-256" + }, + false, + // Non-extractable for enhanced security + ["deriveKey"] + ); + _EnhancedSecureCryptoUtils.secureLog.log("info", "ECDH key pair generated successfully (P-256 fallback)", { + curve: "P-256", + extractable: false + }); + return keyPair; + } + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "ECDH key generation failed", { error: error.message }); + throw new Error("Failed to create keys for secure exchange"); + } + } + // Generate ECDSA key pair for digital signatures with fallback + static async generateECDSAKeyPair() { + try { + try { + const keyPair = await crypto.subtle.generateKey( + { + name: "ECDSA", + namedCurve: "P-384" + }, + false, + // Non-extractable for enhanced security + ["sign", "verify"] + ); + _EnhancedSecureCryptoUtils.secureLog.log("info", "ECDSA key pair generated successfully (P-384)", { + curve: "P-384", + extractable: false + }); + return keyPair; + } catch (p384Error) { + _EnhancedSecureCryptoUtils.secureLog.log("warn", "P-384 generation failed, trying P-256", { error: p384Error.message }); + const keyPair = await crypto.subtle.generateKey( + { + name: "ECDSA", + namedCurve: "P-256" + }, + false, + // Non-extractable for enhanced security + ["sign", "verify"] + ); + _EnhancedSecureCryptoUtils.secureLog.log("info", "ECDSA key pair generated successfully (P-256 fallback)", { + curve: "P-256", + extractable: false + }); + return keyPair; + } + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "ECDSA key generation failed", { error: error.message }); + throw new Error("Failed to generate keys for digital signatures"); + } + } + // Sign data with ECDSA (P-384 or P-256) + static async signData(privateKey, data) { + try { + const encoder = new TextEncoder(); + const dataBuffer = typeof data === "string" ? encoder.encode(data) : data; + try { + const signature = await crypto.subtle.sign( + { + name: "ECDSA", + hash: "SHA-384" + }, + privateKey, + dataBuffer + ); + return Array.from(new Uint8Array(signature)); + } catch (sha384Error) { + _EnhancedSecureCryptoUtils.secureLog.log("warn", "SHA-384 signing failed, trying SHA-256", { error: sha384Error.message }); + const signature = await crypto.subtle.sign( + { + name: "ECDSA", + hash: "SHA-256" + }, + privateKey, + dataBuffer + ); + return Array.from(new Uint8Array(signature)); + } + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Data signing failed", { error: error.message }); + throw new Error("Failed to sign data"); + } + } + // Verify ECDSA signature (P-384 or P-256) + static async verifySignature(publicKey, signature, data) { + try { + const encoder = new TextEncoder(); + const dataBuffer = typeof data === "string" ? encoder.encode(data) : data; + const signatureBuffer = new Uint8Array(signature); + try { + const isValid = await crypto.subtle.verify( + { + name: "ECDSA", + hash: "SHA-384" + }, + publicKey, + signatureBuffer, + dataBuffer + ); + _EnhancedSecureCryptoUtils.secureLog.log("info", "Signature verification completed (SHA-384)", { + isValid, + dataSize: dataBuffer.length + }); + return isValid; + } catch (sha384Error) { + _EnhancedSecureCryptoUtils.secureLog.log("warn", "SHA-384 verification failed, trying SHA-256", { error: sha384Error.message }); + const isValid = await crypto.subtle.verify( + { + name: "ECDSA", + hash: "SHA-256" + }, + publicKey, + signatureBuffer, + dataBuffer + ); + _EnhancedSecureCryptoUtils.secureLog.log("info", "Signature verification completed (SHA-256 fallback)", { + isValid, + dataSize: dataBuffer.length + }); + return isValid; + } + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Signature verification failed", { error: error.message }); + throw new Error("Failed to verify digital signature"); + } + } + // Enhanced DER/SPKI validation with full ASN.1 parsing + static async validateKeyStructure(keyData, expectedAlgorithm = "ECDH") { + try { + if (!Array.isArray(keyData) || keyData.length === 0) { + throw new Error("Invalid key data format"); + } + const keyBytes = new Uint8Array(keyData); + if (keyBytes.length < 50) { + throw new Error("Key data too short - invalid SPKI structure"); + } + if (keyBytes.length > 2e3) { + throw new Error("Key data too long - possible attack"); + } + const asn1 = _EnhancedSecureCryptoUtils.parseASN1(keyBytes); + if (!asn1 || asn1.tag !== 48) { + throw new Error("Invalid SPKI structure - missing SEQUENCE tag"); + } + if (asn1.children.length !== 2) { + throw new Error(`Invalid SPKI structure - expected 2 elements, got ${asn1.children.length}`); + } + const algIdentifier = asn1.children[0]; + if (algIdentifier.tag !== 48) { + throw new Error("Invalid AlgorithmIdentifier - not a SEQUENCE"); + } + const algOid = algIdentifier.children[0]; + if (algOid.tag !== 6) { + throw new Error("Invalid algorithm OID - not an OBJECT IDENTIFIER"); + } + const oidBytes = algOid.value; + const oidString = _EnhancedSecureCryptoUtils.oidToString(oidBytes); + const validAlgorithms = { + "ECDH": ["1.2.840.10045.2.1"], + // id-ecPublicKey + "ECDSA": ["1.2.840.10045.2.1"], + // id-ecPublicKey (same as ECDH) + "RSA": ["1.2.840.113549.1.1.1"], + // rsaEncryption + "AES-GCM": ["2.16.840.1.101.3.4.1.6", "2.16.840.1.101.3.4.1.46"] + // AES-128-GCM, AES-256-GCM + }; + const expectedOids = validAlgorithms[expectedAlgorithm]; + if (!expectedOids) { + throw new Error(`Unknown algorithm: ${expectedAlgorithm}`); + } + if (!expectedOids.includes(oidString)) { + throw new Error(`Invalid algorithm OID: expected ${expectedOids.join(" or ")}, got ${oidString}`); + } + if (expectedAlgorithm === "ECDH" || expectedAlgorithm === "ECDSA") { + if (algIdentifier.children.length < 2) { + throw new Error("Missing curve parameters for EC key"); + } + const curveOid = algIdentifier.children[1]; + if (curveOid.tag !== 6) { + throw new Error("Invalid curve OID - not an OBJECT IDENTIFIER"); + } + const curveOidString = _EnhancedSecureCryptoUtils.oidToString(curveOid.value); + const validCurves = { + "1.2.840.10045.3.1.7": "P-256", + // secp256r1 + "1.3.132.0.34": "P-384" + // secp384r1 + }; + if (!validCurves[curveOidString]) { + throw new Error(`Invalid or unsupported curve OID: ${curveOidString}`); + } + _EnhancedSecureCryptoUtils.secureLog.log("info", "EC key curve validated", { + curve: validCurves[curveOidString], + oid: curveOidString + }); + } + const publicKeyBitString = asn1.children[1]; + if (publicKeyBitString.tag !== 3) { + throw new Error("Invalid public key - not a BIT STRING"); + } + if (publicKeyBitString.value[0] !== 0) { + throw new Error(`Invalid BIT STRING - unexpected unused bits: ${publicKeyBitString.value[0]}`); + } + if (expectedAlgorithm === "ECDH" || expectedAlgorithm === "ECDSA") { + const pointData = publicKeyBitString.value.slice(1); + if (pointData[0] !== 4) { + throw new Error(`Invalid EC point format: expected uncompressed (0x04), got 0x${pointData[0].toString(16)}`); + } + const expectedSizes = { + "P-256": 65, + // 1 + 32 + 32 + "P-384": 97 + // 1 + 48 + 48 + }; + const curveOidString = _EnhancedSecureCryptoUtils.oidToString(algIdentifier.children[1].value); + const curveName = curveOidString === "1.2.840.10045.3.1.7" ? "P-256" : "P-384"; + const expectedSize = expectedSizes[curveName]; + if (pointData.length !== expectedSize) { + throw new Error(`Invalid EC point size for ${curveName}: expected ${expectedSize}, got ${pointData.length}`); + } + } + try { + const algorithm = expectedAlgorithm === "ECDSA" || expectedAlgorithm === "ECDH" ? { name: expectedAlgorithm, namedCurve: "P-384" } : { name: expectedAlgorithm }; + const usages = expectedAlgorithm === "ECDSA" ? ["verify"] : []; + await crypto.subtle.importKey("spki", keyBytes.buffer, algorithm, false, usages); + } catch (importError) { + if (expectedAlgorithm === "ECDSA" || expectedAlgorithm === "ECDH") { + try { + const algorithm = { name: expectedAlgorithm, namedCurve: "P-256" }; + const usages = expectedAlgorithm === "ECDSA" ? ["verify"] : []; + await crypto.subtle.importKey("spki", keyBytes.buffer, algorithm, false, usages); + } catch (fallbackError) { + throw new Error(`Key import validation failed: ${fallbackError.message}`); + } + } else { + throw new Error(`Key import validation failed: ${importError.message}`); + } + } + _EnhancedSecureCryptoUtils.secureLog.log("info", "Key structure validation passed", { + keyLen: keyBytes.length, + algorithm: expectedAlgorithm, + asn1Valid: true, + oidValid: true, + importValid: true + }); + return true; + } catch (err) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Key structure validation failed", { + error: err.message, + algorithm: expectedAlgorithm + }); + throw new Error(`Invalid key structure: ${err.message}`); + } + } + // ASN.1 DER parser helper + static parseASN1(bytes, offset = 0) { + if (offset >= bytes.length) { + return null; + } + const tag = bytes[offset]; + let lengthOffset = offset + 1; + if (lengthOffset >= bytes.length) { + throw new Error("Truncated ASN.1 structure"); + } + let length = bytes[lengthOffset]; + let valueOffset = lengthOffset + 1; + if (length & 128) { + const numLengthBytes = length & 127; + if (numLengthBytes > 4) { + throw new Error("ASN.1 length too large"); + } + length = 0; + for (let i = 0; i < numLengthBytes; i++) { + if (valueOffset + i >= bytes.length) { + throw new Error("Truncated ASN.1 length"); + } + length = length << 8 | bytes[valueOffset + i]; + } + valueOffset += numLengthBytes; + } + if (valueOffset + length > bytes.length) { + throw new Error("ASN.1 structure extends beyond data"); + } + const value = bytes.slice(valueOffset, valueOffset + length); + const node = { + tag, + length, + value, + children: [] + }; + if (tag === 48 || tag === 49) { + let childOffset = 0; + while (childOffset < value.length) { + const child = _EnhancedSecureCryptoUtils.parseASN1(value, childOffset); + if (!child) break; + node.children.push(child); + childOffset = childOffset + 1 + child.lengthBytes + child.length; + } + } + node.lengthBytes = valueOffset - lengthOffset; + return node; + } + // OID decoder helper + static oidToString(bytes) { + if (!bytes || bytes.length === 0) { + throw new Error("Empty OID"); + } + const parts = []; + const first = Math.floor(bytes[0] / 40); + const second = bytes[0] % 40; + parts.push(first); + parts.push(second); + let value = 0; + for (let i = 1; i < bytes.length; i++) { + value = value << 7 | bytes[i] & 127; + if (!(bytes[i] & 128)) { + parts.push(value); + value = 0; + } + } + return parts.join("."); + } + // Helper to validate and sanitize OID string + static validateOidString(oidString) { + const oidRegex = /^[0-9]+(\.[0-9]+)*$/; + if (!oidRegex.test(oidString)) { + throw new Error(`Invalid OID format: ${oidString}`); + } + const parts = oidString.split(".").map(Number); + if (parts[0] > 2) { + throw new Error(`Invalid OID first component: ${parts[0]}`); + } + if ((parts[0] === 0 || parts[0] === 1) && parts[1] > 39) { + throw new Error(`Invalid OID second component: ${parts[1]} (must be <= 39 for first component ${parts[0]})`); + } + return true; + } + // Export public key for transmission with signature + static async exportPublicKeyWithSignature(publicKey, signingKey, keyType = "ECDH") { + try { + if (!["ECDH", "ECDSA"].includes(keyType)) { + throw new Error("Invalid key type"); + } + const exported = await crypto.subtle.exportKey("spki", publicKey); + const keyData = Array.from(new Uint8Array(exported)); + await _EnhancedSecureCryptoUtils.validateKeyStructure(keyData, keyType); + const keyPackage = { + keyType, + keyData, + timestamp: Date.now(), + version: "4.0" + }; + const packageString = JSON.stringify(keyPackage); + const signature = await _EnhancedSecureCryptoUtils.signData(signingKey, packageString); + const signedPackage = { + ...keyPackage, + signature + }; + _EnhancedSecureCryptoUtils.secureLog.log("info", "Public key exported with signature", { + keyType, + keySize: keyData.length, + signed: true + }); + return signedPackage; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Public key export failed", { + error: error.message, + keyType + }); + throw new Error(`Failed to export ${keyType} key: ${error.message}`); + } + } + // Import and verify signed public key + static async importSignedPublicKey(signedPackage, verifyingKey, expectedKeyType = "ECDH") { + try { + if (!signedPackage || typeof signedPackage !== "object") { + throw new Error("Invalid signed package format"); + } + const { keyType, keyData, timestamp, version, signature } = signedPackage; + if (!keyType || !keyData || !timestamp || !signature) { + throw new Error("Missing required fields in signed package"); + } + if (!_EnhancedSecureCryptoUtils.constantTimeCompare(keyType, expectedKeyType)) { + throw new Error(`Key type mismatch: expected ${expectedKeyType}, got ${keyType}`); + } + const keyAge = Date.now() - timestamp; + if (keyAge > 36e5) { + throw new Error("Signed key package is too old"); + } + await _EnhancedSecureCryptoUtils.validateKeyStructure(keyData, keyType); + const packageCopy = { keyType, keyData, timestamp, version }; + const packageString = JSON.stringify(packageCopy); + const isValidSignature = await _EnhancedSecureCryptoUtils.verifySignature(verifyingKey, signature, packageString); + if (!isValidSignature) { + throw new Error("Invalid signature on key package - possible MITM attack"); + } + const keyBytes = new Uint8Array(keyData); + try { + const algorithm = keyType === "ECDH" ? { name: "ECDH", namedCurve: "P-384" } : { name: "ECDSA", namedCurve: "P-384" }; + const keyUsages = keyType === "ECDH" ? [] : ["verify"]; + const publicKey = await crypto.subtle.importKey( + "spki", + keyBytes, + algorithm, + false, + // Non-extractable + keyUsages + ); + _EnhancedSecureCryptoUtils.secureLog.log("info", "Signed public key imported successfully (P-384)", { + keyType, + signatureValid: true, + keyAge: Math.round(keyAge / 1e3) + "s" + }); + return publicKey; + } catch (p384Error) { + _EnhancedSecureCryptoUtils.secureLog.log("warn", "P-384 import failed, trying P-256", { + error: p384Error.message + }); + const algorithm = keyType === "ECDH" ? { name: "ECDH", namedCurve: "P-256" } : { name: "ECDSA", namedCurve: "P-256" }; + const keyUsages = keyType === "ECDH" ? [] : ["verify"]; + const publicKey = await crypto.subtle.importKey( + "spki", + keyBytes, + algorithm, + false, + // Non-extractable + keyUsages + ); + _EnhancedSecureCryptoUtils.secureLog.log("info", "Signed public key imported successfully (P-256 fallback)", { + keyType, + signatureValid: true, + keyAge: Math.round(keyAge / 1e3) + "s" + }); + return publicKey; + } + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Signed public key import failed", { + error: error.message, + expectedKeyType + }); + throw new Error(`Failed to import the signed key: ${error.message}`); + } + } + // Legacy export for backward compatibility + static async exportPublicKey(publicKey) { + try { + const exported = await crypto.subtle.exportKey("spki", publicKey); + const keyData = Array.from(new Uint8Array(exported)); + await _EnhancedSecureCryptoUtils.validateKeyStructure(keyData, "ECDH"); + _EnhancedSecureCryptoUtils.secureLog.log("info", "Legacy public key exported", { keySize: keyData.length }); + return keyData; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Legacy public key export failed", { error: error.message }); + throw new Error("Failed to export the public key"); + } + } + // Legacy import for backward compatibility with fallback + static async importPublicKey(keyData) { + try { + await _EnhancedSecureCryptoUtils.validateKeyStructure(keyData, "ECDH"); + const keyBytes = new Uint8Array(keyData); + try { + const publicKey = await crypto.subtle.importKey( + "spki", + keyBytes, + { + name: "ECDH", + namedCurve: "P-384" + }, + false, + // Non-extractable + [] + ); + _EnhancedSecureCryptoUtils.secureLog.log("info", "Legacy public key imported (P-384)", { keySize: keyData.length }); + return publicKey; + } catch (p384Error) { + _EnhancedSecureCryptoUtils.secureLog.log("warn", "P-384 import failed, trying P-256", { error: p384Error.message }); + const publicKey = await crypto.subtle.importKey( + "spki", + keyBytes, + { + name: "ECDH", + namedCurve: "P-256" + }, + false, + // Non-extractable + [] + ); + _EnhancedSecureCryptoUtils.secureLog.log("info", "Legacy public key imported (P-256 fallback)", { keySize: keyData.length }); + return publicKey; + } + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Legacy public key import failed", { error: error.message }); + throw new Error("Failed to import the public key"); + } + } + // Method to check if a key is trusted + static isKeyTrusted(keyOrFingerprint) { + if (keyOrFingerprint instanceof CryptoKey) { + const meta = _EnhancedSecureCryptoUtils._keyMetadata.get(keyOrFingerprint); + return meta ? meta.trusted === true : false; + } else if (keyOrFingerprint && keyOrFingerprint._securityMetadata) { + return keyOrFingerprint._securityMetadata.trusted === true; + } + return false; + } + static async importPublicKeyFromSignedPackage(signedPackage, verifyingKey = null, options = {}) { + try { + if (!signedPackage || !signedPackage.keyData || !signedPackage.signature) { + throw new Error("Invalid signed key package format"); + } + const requiredFields = ["keyData", "signature", "keyType", "timestamp", "version"]; + const missingFields = requiredFields.filter((field) => !signedPackage[field]); + if (missingFields.length > 0) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Missing required fields in signed package", { + missingFields, + availableFields: Object.keys(signedPackage) + }); + throw new Error(`Required fields are missing in the signed package: ${missingFields.join(", ")}`); + } + if (!verifyingKey) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "SECURITY VIOLATION: Signed package received without verifying key", { + keyType: signedPackage.keyType, + keySize: signedPackage.keyData.length, + timestamp: signedPackage.timestamp, + version: signedPackage.version, + securityRisk: "HIGH - Potential MITM attack vector" + }); + throw new Error("CRITICAL SECURITY ERROR: Signed key package received without a verification key. This may indicate a possible MITM attack attempt. Import rejected for security reasons."); + } + await _EnhancedSecureCryptoUtils.validateKeyStructure(signedPackage.keyData, signedPackage.keyType || "ECDH"); + const packageCopy = { ...signedPackage }; + delete packageCopy.signature; + const packageString = JSON.stringify(packageCopy); + const isValidSignature = await _EnhancedSecureCryptoUtils.verifySignature(verifyingKey, signedPackage.signature, packageString); + if (!isValidSignature) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "SECURITY BREACH: Invalid signature detected - MITM attack prevented", { + keyType: signedPackage.keyType, + keySize: signedPackage.keyData.length, + timestamp: signedPackage.timestamp, + version: signedPackage.version, + attackPrevented: true + }); + throw new Error("CRITICAL SECURITY ERROR: Invalid key signature detected. This indicates a possible MITM attack attempt. Key import rejected."); + } + const keyFingerprint = await _EnhancedSecureCryptoUtils.calculateKeyFingerprint(signedPackage.keyData); + _EnhancedSecureCryptoUtils.secureLog.log("info", "SECURE: Signature verification passed for signed package", { + keyType: signedPackage.keyType, + keySize: signedPackage.keyData.length, + timestamp: signedPackage.timestamp, + version: signedPackage.version, + signatureVerified: true, + securityLevel: "HIGH", + keyFingerprint: keyFingerprint.substring(0, 8) + // Only log first 8 chars for security + }); + const keyBytes = new Uint8Array(signedPackage.keyData); + const keyType = signedPackage.keyType || "ECDH"; + try { + const publicKey = await crypto.subtle.importKey( + "spki", + keyBytes, + { + name: keyType, + namedCurve: "P-384" + }, + false, + // Non-extractable + keyType === "ECDSA" ? ["verify"] : [] + ); + _EnhancedSecureCryptoUtils._keyMetadata.set(publicKey, { + trusted: true, + verificationStatus: "VERIFIED_SECURE", + verificationTimestamp: Date.now() + }); + return publicKey; + } catch (p384Error) { + _EnhancedSecureCryptoUtils.secureLog.log("warn", "P-384 import failed, trying P-256", { error: p384Error.message }); + const publicKey = await crypto.subtle.importKey( + "spki", + keyBytes, + { + name: keyType, + namedCurve: "P-256" + }, + false, + // Non-extractable + keyType === "ECDSA" ? ["verify"] : [] + ); + _EnhancedSecureCryptoUtils._keyMetadata.set(publicKey, { + trusted: true, + verificationStatus: "VERIFIED_SECURE", + verificationTimestamp: Date.now() + }); + return publicKey; + } + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Signed package key import failed", { + error: error.message, + securityImplications: "Potential security breach prevented" + }); + throw new Error(`Failed to import the public key from the signed package: ${error.message}`); + } + } + // Enhanced key derivation with metadata protection and 64-byte salt + static async deriveSharedKeys(privateKey, publicKey, salt) { + try { + if (!(privateKey instanceof CryptoKey)) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Private key is not a CryptoKey", { + privateKeyType: typeof privateKey, + privateKeyAlgorithm: privateKey?.algorithm?.name + }); + throw new Error("The private key is not a valid CryptoKey."); + } + if (!(publicKey instanceof CryptoKey)) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Public key is not a CryptoKey", { + publicKeyType: typeof publicKey, + publicKeyAlgorithm: publicKey?.algorithm?.name + }); + throw new Error("The private key is not a valid CryptoKey."); + } + if (!salt || salt.length !== 64) { + throw new Error("Salt must be exactly 64 bytes for enhanced security"); + } + const saltBytes = new Uint8Array(salt); + const encoder = new TextEncoder(); + const contextInfo = encoder.encode("SecureBit.chat v4.0 Enhanced Security Edition"); + let sharedSecret; + try { + sharedSecret = await crypto.subtle.deriveKey( + { + name: "ECDH", + public: publicKey + }, + privateKey, + { + name: "HKDF", + hash: "SHA-384", + salt: saltBytes, + info: contextInfo + }, + false, + // Non-extractable + ["deriveKey"] + ); + } catch (sha384Error) { + _EnhancedSecureCryptoUtils.secureLog.log("warn", "SHA-384 key derivation failed, trying SHA-256", { + error: sha384Error.message, + privateKeyType: typeof privateKey, + publicKeyType: typeof publicKey, + privateKeyAlgorithm: privateKey?.algorithm?.name, + publicKeyAlgorithm: publicKey?.algorithm?.name + }); + sharedSecret = await crypto.subtle.deriveKey( + { + name: "ECDH", + public: publicKey + }, + privateKey, + { + name: "HKDF", + hash: "SHA-256", + salt: saltBytes, + info: contextInfo + }, + false, + // Non-extractable + ["deriveKey"] + ); + } + let encryptionKey; + try { + encryptionKey = await crypto.subtle.deriveKey( + { + name: "HKDF", + hash: "SHA-384", + salt: saltBytes, + info: encoder.encode("message-encryption-v4") + }, + sharedSecret, + { + name: "AES-GCM", + length: 256 + }, + false, + // Non-extractable for enhanced security + ["encrypt", "decrypt"] + ); + } catch (sha384Error) { + encryptionKey = await crypto.subtle.deriveKey( + { + name: "HKDF", + hash: "SHA-256", + salt: saltBytes, + info: encoder.encode("message-encryption-v4") + }, + sharedSecret, + { + name: "AES-GCM", + length: 256 + }, + false, + // Non-extractable for enhanced security + ["encrypt", "decrypt"] + ); + } + let macKey; + try { + macKey = await crypto.subtle.deriveKey( + { + name: "HKDF", + hash: "SHA-384", + salt: saltBytes, + info: encoder.encode("message-authentication-v4") + }, + sharedSecret, + { + name: "HMAC", + hash: "SHA-384" + }, + false, + // Non-extractable + ["sign", "verify"] + ); + } catch (sha384Error) { + macKey = await crypto.subtle.deriveKey( + { + name: "HKDF", + hash: "SHA-256", + salt: saltBytes, + info: encoder.encode("message-authentication-v4") + }, + sharedSecret, + { + name: "HMAC", + hash: "SHA-256" + }, + false, + // Non-extractable + ["sign", "verify"] + ); + } + let metadataKey; + try { + metadataKey = await crypto.subtle.deriveKey( + { + name: "HKDF", + hash: "SHA-384", + salt: saltBytes, + info: encoder.encode("metadata-protection-v4") + }, + sharedSecret, + { + name: "AES-GCM", + length: 256 + }, + false, + // Non-extractable + ["encrypt", "decrypt"] + ); + } catch (sha384Error) { + metadataKey = await crypto.subtle.deriveKey( + { + name: "HKDF", + hash: "SHA-256", + salt: saltBytes, + info: encoder.encode("metadata-protection-v4") + }, + sharedSecret, + { + name: "AES-GCM", + length: 256 + }, + false, + // Non-extractable + ["encrypt", "decrypt"] + ); + } + let fingerprintKey; + try { + fingerprintKey = await crypto.subtle.deriveKey( + { + name: "HKDF", + hash: "SHA-384", + salt: saltBytes, + info: encoder.encode("fingerprint-generation-v4") + }, + sharedSecret, + { + name: "AES-GCM", + length: 256 + }, + true, + // Extractable only for fingerprint + ["encrypt", "decrypt"] + ); + } catch (sha384Error) { + fingerprintKey = await crypto.subtle.deriveKey( + { + name: "HKDF", + hash: "SHA-256", + salt: saltBytes, + info: encoder.encode("fingerprint-generation-v4") + }, + sharedSecret, + { + name: "AES-GCM", + length: 256 + }, + true, + // Extractable only for fingerprint + ["encrypt", "decrypt"] + ); + } + const fingerprintKeyData = await crypto.subtle.exportKey("raw", fingerprintKey); + const fingerprint = await _EnhancedSecureCryptoUtils.generateKeyFingerprint(Array.from(new Uint8Array(fingerprintKeyData))); + if (!(encryptionKey instanceof CryptoKey)) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Derived encryption key is not a CryptoKey", { + encryptionKeyType: typeof encryptionKey, + encryptionKeyAlgorithm: encryptionKey?.algorithm?.name + }); + throw new Error("The derived encryption key is not a valid CryptoKey."); + } + if (!(macKey instanceof CryptoKey)) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Derived MAC key is not a CryptoKey", { + macKeyType: typeof macKey, + macKeyAlgorithm: macKey?.algorithm?.name + }); + throw new Error("The derived MAC key is not a valid CryptoKey."); + } + if (!(metadataKey instanceof CryptoKey)) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Derived metadata key is not a CryptoKey", { + metadataKeyType: typeof metadataKey, + metadataKeyAlgorithm: metadataKey?.algorithm?.name + }); + throw new Error("The derived metadata key is not a valid CryptoKey."); + } + _EnhancedSecureCryptoUtils.secureLog.log("info", "Enhanced shared keys derived successfully", { + saltSize: salt.length, + hasMetadataKey: true, + nonExtractable: true, + version: "4.0", + allKeysValid: true + }); + return { + encryptionKey, + macKey, + metadataKey, + fingerprint, + timestamp: Date.now(), + version: "4.0" + }; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Enhanced key derivation failed", { error: error.message }); + throw new Error(`Failed to create shared encryption keys: ${error.message}`); + } + } + static async generateKeyFingerprint(keyData) { + const keyBuffer = new Uint8Array(keyData); + const hashBuffer = await crypto.subtle.digest("SHA-384", keyBuffer); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + return hashArray.slice(0, 12).map((b) => b.toString(16).padStart(2, "0")).join(":"); + } + // Generate mutual authentication challenge + static generateMutualAuthChallenge() { + const challenge = crypto.getRandomValues(new Uint8Array(48)); + const timestamp = Date.now(); + const nonce = crypto.getRandomValues(new Uint8Array(16)); + return { + challenge: Array.from(challenge), + timestamp, + nonce: Array.from(nonce), + version: "4.0" + }; + } + // Create cryptographic proof for mutual authentication + static async createAuthProof(challenge, privateKey, publicKey) { + try { + if (!challenge || !challenge.challenge || !challenge.timestamp || !challenge.nonce) { + throw new Error("Invalid challenge structure"); + } + const challengeAge = Date.now() - challenge.timestamp; + if (challengeAge > 12e4) { + throw new Error("Challenge expired"); + } + const proofData = { + challenge: challenge.challenge, + timestamp: challenge.timestamp, + nonce: challenge.nonce, + responseTimestamp: Date.now(), + publicKeyHash: await _EnhancedSecureCryptoUtils.hashPublicKey(publicKey) + }; + const proofString = JSON.stringify(proofData); + const signature = await _EnhancedSecureCryptoUtils.signData(privateKey, proofString); + const proof = { + ...proofData, + signature, + version: "4.0" + }; + _EnhancedSecureCryptoUtils.secureLog.log("info", "Authentication proof created", { + challengeAge: Math.round(challengeAge / 1e3) + "s" + }); + return proof; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Authentication proof creation failed", { error: error.message }); + throw new Error(`Failed to create cryptographic proof: ${error.message}`); + } + } + // Verify mutual authentication proof + static async verifyAuthProof(proof, challenge, publicKey) { + try { + await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * 20) + 5)); + _EnhancedSecureCryptoUtils.assertCryptoKey(publicKey, "ECDSA", ["verify"]); + if (!proof || !challenge || !publicKey) { + throw new Error("Missing required parameters for proof verification"); + } + const requiredFields = ["challenge", "timestamp", "nonce", "responseTimestamp", "publicKeyHash", "signature"]; + for (const field of requiredFields) { + if (!proof[field]) { + throw new Error(`Missing required field: ${field}`); + } + } + if (!_EnhancedSecureCryptoUtils.constantTimeCompareArrays(proof.challenge, challenge.challenge) || proof.timestamp !== challenge.timestamp || !_EnhancedSecureCryptoUtils.constantTimeCompareArrays(proof.nonce, challenge.nonce)) { + throw new Error("Challenge mismatch - possible replay attack"); + } + const responseAge = Date.now() - proof.responseTimestamp; + if (responseAge > 3e5) { + throw new Error("Proof response expired"); + } + const expectedHash = await _EnhancedSecureCryptoUtils.hashPublicKey(publicKey); + if (!_EnhancedSecureCryptoUtils.constantTimeCompare(proof.publicKeyHash, expectedHash)) { + throw new Error("Public key hash mismatch"); + } + const proofCopy = { ...proof }; + delete proofCopy.signature; + const proofString = JSON.stringify(proofCopy); + const isValidSignature = await _EnhancedSecureCryptoUtils.verifySignature(publicKey, proof.signature, proofString); + if (!isValidSignature) { + throw new Error("Invalid proof signature"); + } + _EnhancedSecureCryptoUtils.secureLog.log("info", "Authentication proof verified successfully", { + responseAge: Math.round(responseAge / 1e3) + "s" + }); + return true; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Authentication proof verification failed", { error: error.message }); + throw new Error(`Failed to verify cryptographic proof: ${error.message}`); + } + } + // Hash public key for verification + static async hashPublicKey(publicKey) { + try { + const exported = await crypto.subtle.exportKey("spki", publicKey); + const hash = await crypto.subtle.digest("SHA-384", exported); + const hashArray = Array.from(new Uint8Array(hash)); + return hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Public key hashing failed", { error: error.message }); + throw new Error("Failed to create hash of the public key"); + } + } + // Legacy authentication challenge for backward compatibility + static generateAuthChallenge() { + const challenge = crypto.getRandomValues(new Uint8Array(32)); + return Array.from(challenge); + } + // Generate verification code for out-of-band authentication + static generateVerificationCode() { + const chars = "0123456789ABCDEF"; + let result = ""; + const values = crypto.getRandomValues(new Uint8Array(6)); + for (let i = 0; i < 6; i++) { + result += chars[values[i] % chars.length]; + } + return result.match(/.{1,2}/g).join("-"); + } + // Enhanced message encryption with metadata protection and sequence numbers + static async encryptMessage(message, encryptionKey, macKey, metadataKey, messageId, sequenceNumber = 0) { + try { + if (!message || typeof message !== "string") { + throw new Error("Invalid message format"); + } + _EnhancedSecureCryptoUtils.assertCryptoKey(encryptionKey, "AES-GCM", ["encrypt"]); + _EnhancedSecureCryptoUtils.assertCryptoKey(macKey, "HMAC", ["sign"]); + _EnhancedSecureCryptoUtils.assertCryptoKey(metadataKey, "AES-GCM", ["encrypt"]); + const encoder = new TextEncoder(); + const messageData = encoder.encode(message); + const messageIv = crypto.getRandomValues(new Uint8Array(12)); + const metadataIv = crypto.getRandomValues(new Uint8Array(12)); + const timestamp = Date.now(); + const paddingSize = 16 - messageData.length % 16; + const paddedMessage = new Uint8Array(messageData.length + paddingSize); + paddedMessage.set(messageData); + const padding = crypto.getRandomValues(new Uint8Array(paddingSize)); + paddedMessage.set(padding, messageData.length); + const encryptedMessage = await crypto.subtle.encrypt( + { name: "AES-GCM", iv: messageIv }, + encryptionKey, + paddedMessage + ); + const metadata = { + id: messageId, + timestamp, + sequenceNumber, + originalLength: messageData.length, + version: "4.0" + }; + const metadataStr = JSON.stringify(_EnhancedSecureCryptoUtils.sortObjectKeys(metadata)); + const encryptedMetadata = await crypto.subtle.encrypt( + { name: "AES-GCM", iv: metadataIv }, + metadataKey, + encoder.encode(metadataStr) + ); + const payload = { + messageIv: Array.from(messageIv), + messageData: Array.from(new Uint8Array(encryptedMessage)), + metadataIv: Array.from(metadataIv), + metadataData: Array.from(new Uint8Array(encryptedMetadata)), + version: "4.0" + }; + const sortedPayload = _EnhancedSecureCryptoUtils.sortObjectKeys(payload); + const payloadStr = JSON.stringify(sortedPayload); + const mac = await crypto.subtle.sign( + "HMAC", + macKey, + encoder.encode(payloadStr) + ); + payload.mac = Array.from(new Uint8Array(mac)); + _EnhancedSecureCryptoUtils.secureLog.log("info", "Message encrypted with metadata protection", { + messageId, + sequenceNumber, + hasMetadataProtection: true, + hasPadding: true + }); + return payload; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Message encryption failed", { + error: error.message, + messageId + }); + throw new Error(`Failed to encrypt the message: ${error.message}`); + } + } + // Enhanced message decryption with metadata protection and sequence validation + static async decryptMessage(encryptedPayload, encryptionKey, macKey, metadataKey, expectedSequenceNumber = null) { + try { + _EnhancedSecureCryptoUtils.assertCryptoKey(encryptionKey, "AES-GCM", ["decrypt"]); + _EnhancedSecureCryptoUtils.assertCryptoKey(macKey, "HMAC", ["verify"]); + _EnhancedSecureCryptoUtils.assertCryptoKey(metadataKey, "AES-GCM", ["decrypt"]); + const requiredFields = ["messageIv", "messageData", "metadataIv", "metadataData", "mac", "version"]; + for (const field of requiredFields) { + if (!encryptedPayload[field]) { + throw new Error(`Missing required field: ${field}`); + } + } + const payloadCopy = { ...encryptedPayload }; + delete payloadCopy.mac; + const sortedPayloadCopy = _EnhancedSecureCryptoUtils.sortObjectKeys(payloadCopy); + const payloadStr = JSON.stringify(sortedPayloadCopy); + const macValid = await crypto.subtle.verify( + "HMAC", + macKey, + new Uint8Array(encryptedPayload.mac), + new TextEncoder().encode(payloadStr) + ); + if (!macValid) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "MAC verification failed", { + payloadFields: Object.keys(encryptedPayload), + macLength: encryptedPayload.mac?.length + }); + throw new Error("Message authentication failed - possible tampering"); + } + const metadataIv = new Uint8Array(encryptedPayload.metadataIv); + const metadataData = new Uint8Array(encryptedPayload.metadataData); + const decryptedMetadataBuffer = await crypto.subtle.decrypt( + { name: "AES-GCM", iv: metadataIv }, + metadataKey, + metadataData + ); + const metadataStr = new TextDecoder().decode(decryptedMetadataBuffer); + const metadata = JSON.parse(metadataStr); + if (!metadata.id || !metadata.timestamp || metadata.sequenceNumber === void 0 || !metadata.originalLength) { + throw new Error("Invalid metadata structure"); + } + const messageAge = Date.now() - metadata.timestamp; + if (messageAge > 3e5) { + throw new Error("Message expired (older than 5 minutes)"); + } + if (expectedSequenceNumber !== null) { + if (metadata.sequenceNumber < expectedSequenceNumber) { + _EnhancedSecureCryptoUtils.secureLog.log("warn", "Received message with lower sequence number, possible queued message", { + expected: expectedSequenceNumber, + received: metadata.sequenceNumber, + messageId: metadata.id + }); + } else if (metadata.sequenceNumber > expectedSequenceNumber + 10) { + throw new Error(`Sequence number gap too large: expected around ${expectedSequenceNumber}, got ${metadata.sequenceNumber}`); + } + } + const messageIv = new Uint8Array(encryptedPayload.messageIv); + const messageData = new Uint8Array(encryptedPayload.messageData); + const decryptedMessageBuffer = await crypto.subtle.decrypt( + { name: "AES-GCM", iv: messageIv }, + encryptionKey, + messageData + ); + const paddedMessage = new Uint8Array(decryptedMessageBuffer); + const originalMessage = paddedMessage.slice(0, metadata.originalLength); + const decoder = new TextDecoder(); + const message = decoder.decode(originalMessage); + _EnhancedSecureCryptoUtils.secureLog.log("info", "Message decrypted successfully", { + messageId: metadata.id, + sequenceNumber: metadata.sequenceNumber, + messageAge: Math.round(messageAge / 1e3) + "s" + }); + return { + message, + messageId: metadata.id, + timestamp: metadata.timestamp, + sequenceNumber: metadata.sequenceNumber + }; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Message decryption failed", { error: error.message }); + throw new Error(`Failed to decrypt the message: ${error.message}`); + } + } + // Enhanced input sanitization + static sanitizeMessage(message) { + if (typeof message !== "string") { + throw new Error("Message must be a string"); + } + return message.replace(/)<[^<]*)*<\/script>/gi, "").replace(/javascript:/gi, "").replace(/data:/gi, "").replace(/vbscript:/gi, "").replace(/onload\s*=/gi, "").replace(/onerror\s*=/gi, "").replace(/onclick\s*=/gi, "").trim().substring(0, 2e3); + } + // Generate cryptographically secure salt (64 bytes for enhanced security) + static generateSalt() { + return Array.from(crypto.getRandomValues(new Uint8Array(64))); + } + // Calculate key fingerprint for MITM protection + static async calculateKeyFingerprint(keyData) { + try { + const encoder = new TextEncoder(); + const keyBytes = new Uint8Array(keyData); + const hashBuffer = await crypto.subtle.digest("SHA-256", keyBytes); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const fingerprint = hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); + _EnhancedSecureCryptoUtils.secureLog.log("info", "Key fingerprint calculated", { + keySize: keyData.length, + fingerprintLength: fingerprint.length + }); + return fingerprint; + } catch (error) { + _EnhancedSecureCryptoUtils.secureLog.log("error", "Key fingerprint calculation failed", { error: error.message }); + throw new Error("Failed to compute the key fingerprint"); + } + } + static constantTimeCompare(a, b) { + const strA = typeof a === "string" ? a : JSON.stringify(a); + const strB = typeof b === "string" ? b : JSON.stringify(b); + if (strA.length !== strB.length) { + let dummy = 0; + for (let i = 0; i < Math.max(strA.length, strB.length); i++) { + dummy |= (strA.charCodeAt(i % strA.length) || 0) ^ (strB.charCodeAt(i % strB.length) || 0); + } + return false; + } + let result = 0; + for (let i = 0; i < strA.length; i++) { + result |= strA.charCodeAt(i) ^ strB.charCodeAt(i); + } + return result === 0; + } + static constantTimeCompareArrays(arr1, arr2) { + if (!Array.isArray(arr1) || !Array.isArray(arr2)) { + return false; + } + if (arr1.length !== arr2.length) { + let dummy = 0; + const maxLen = Math.max(arr1.length, arr2.length); + for (let i = 0; i < maxLen; i++) { + dummy |= (arr1[i % arr1.length] || 0) ^ (arr2[i % arr2.length] || 0); + } + return false; + } + let result = 0; + for (let i = 0; i < arr1.length; i++) { + result |= arr1[i] ^ arr2[i]; + } + return result === 0; + } + /** + * CRITICAL SECURITY: Encrypt data with AAD (Additional Authenticated Data) + * This method provides authenticated encryption with additional data binding + */ + static async encryptDataWithAAD(data, key, aad) { + try { + const dataString = typeof data === "string" ? data : JSON.stringify(data); + const encoder = new TextEncoder(); + const dataBuffer = encoder.encode(dataString); + const aadBuffer = encoder.encode(aad); + const iv = crypto.getRandomValues(new Uint8Array(12)); + const encrypted = await crypto.subtle.encrypt( + { + name: "AES-GCM", + iv, + additionalData: aadBuffer + }, + key, + dataBuffer + ); + const encryptedPackage = { + version: "1.0", + iv: Array.from(iv), + data: Array.from(new Uint8Array(encrypted)), + aad, + timestamp: Date.now() + }; + const packageString = JSON.stringify(encryptedPackage); + const packageBuffer = encoder.encode(packageString); + return _EnhancedSecureCryptoUtils.arrayBufferToBase64(packageBuffer); + } catch (error) { + throw new Error(`AAD encryption failed: ${error.message}`); + } + } + /** + * CRITICAL SECURITY: Decrypt data with AAD validation + * This method provides authenticated decryption with additional data validation + */ + static async decryptDataWithAAD(encryptedData, key, expectedAad) { + try { + const packageBuffer = _EnhancedSecureCryptoUtils.base64ToArrayBuffer(encryptedData); + const packageString = new TextDecoder().decode(packageBuffer); + const encryptedPackage = JSON.parse(packageString); + if (!encryptedPackage.version || !encryptedPackage.iv || !encryptedPackage.data || !encryptedPackage.aad) { + throw new Error("Invalid encrypted data format"); + } + if (encryptedPackage.aad !== expectedAad) { + throw new Error("AAD mismatch - possible tampering or replay attack"); + } + const iv = new Uint8Array(encryptedPackage.iv); + const encrypted = new Uint8Array(encryptedPackage.data); + const aadBuffer = new TextEncoder().encode(encryptedPackage.aad); + const decrypted = await crypto.subtle.decrypt( + { + name: "AES-GCM", + iv, + additionalData: aadBuffer + }, + key, + encrypted + ); + const decryptedString = new TextDecoder().decode(decrypted); + try { + return JSON.parse(decryptedString); + } catch { + return decryptedString; + } + } catch (error) { + throw new Error(`AAD decryption failed: ${error.message}`); + } + } + static { + if (_EnhancedSecureCryptoUtils.secureLog && typeof _EnhancedSecureCryptoUtils.secureLog.init === "function") { + _EnhancedSecureCryptoUtils.secureLog.init(); + } + } +}; + +// src/transfer/EnhancedSecureFileTransfer.js +var SecureFileTransferContext = class _SecureFileTransferContext { + static #instance = null; + static #contextKey = Symbol("SecureFileTransferContext"); + static getInstance() { + if (!this.#instance) { + this.#instance = new _SecureFileTransferContext(); + } + return this.#instance; + } + #fileTransferSystem = null; + #active = false; + #securityLevel = "high"; + setFileTransferSystem(system) { + if (!(system instanceof EnhancedSecureFileTransfer)) { + throw new Error("Invalid file transfer system instance"); + } + this.#fileTransferSystem = system; + this.#active = true; + console.log("\u{1F512} Secure file transfer context initialized"); + } + getFileTransferSystem() { + return this.#fileTransferSystem; + } + isActive() { + return this.#active && this.#fileTransferSystem !== null; + } + deactivate() { + this.#active = false; + this.#fileTransferSystem = null; + console.log("\u{1F512} Secure file transfer context deactivated"); + } + getSecurityLevel() { + return this.#securityLevel; + } + setSecurityLevel(level) { + if (["low", "medium", "high"].includes(level)) { + this.#securityLevel = level; + } + } +}; +var SecurityErrorHandler = class { + static #allowedErrors = /* @__PURE__ */ new Set([ + "File size exceeds maximum limit", + "Unsupported file type", + "Transfer timeout", + "Connection lost", + "Invalid file data", + "File transfer failed", + "Transfer cancelled", + "Network error", + "File not found", + "Permission denied" + ]); + static sanitizeError(error) { + const message = error.message || error; + for (const allowed of this.#allowedErrors) { + if (message.includes(allowed)) { + return allowed; + } + } + console.error("\u{1F512} Internal file transfer error:", { + message: error.message, + stack: error.stack, + timestamp: (/* @__PURE__ */ new Date()).toISOString() + }); + return "File transfer failed"; + } + static logSecurityEvent(event, details = {}) { + console.warn("\u{1F512} Security event:", { + event, + timestamp: (/* @__PURE__ */ new Date()).toISOString(), + ...details + }); + } +}; +var FileMetadataSigner = class { + static async signFileMetadata(metadata, privateKey) { + try { + const encoder = new TextEncoder(); + const data = encoder.encode(JSON.stringify({ + fileId: metadata.fileId, + fileName: metadata.fileName, + fileSize: metadata.fileSize, + fileHash: metadata.fileHash, + timestamp: metadata.timestamp, + version: metadata.version || "2.0" + })); + const signature = await crypto.subtle.sign( + "RSASSA-PKCS1-v1_5", + privateKey, + data + ); + return Array.from(new Uint8Array(signature)); + } catch (error) { + SecurityErrorHandler.logSecurityEvent("signature_failed", { error: error.message }); + throw new Error("Failed to sign file metadata"); + } + } + static async verifyFileMetadata(metadata, signature, publicKey) { + try { + const encoder = new TextEncoder(); + const data = encoder.encode(JSON.stringify({ + fileId: metadata.fileId, + fileName: metadata.fileName, + fileSize: metadata.fileSize, + fileHash: metadata.fileHash, + timestamp: metadata.timestamp, + version: metadata.version || "2.0" + })); + const signatureBuffer = new Uint8Array(signature); + const isValid = await crypto.subtle.verify( + "RSASSA-PKCS1-v1_5", + publicKey, + signatureBuffer, + data + ); + if (!isValid) { + SecurityErrorHandler.logSecurityEvent("invalid_signature", { fileId: metadata.fileId }); + } + return isValid; + } catch (error) { + SecurityErrorHandler.logSecurityEvent("verification_failed", { error: error.message }); + return false; + } + } +}; +var MessageSizeValidator = class { + static MAX_MESSAGE_SIZE = 1024 * 1024; + // 1MB + static isMessageSizeValid(message) { + const messageString = JSON.stringify(message); + const sizeInBytes = new Blob([messageString]).size; + if (sizeInBytes > this.MAX_MESSAGE_SIZE) { + SecurityErrorHandler.logSecurityEvent("message_too_large", { + size: sizeInBytes, + limit: this.MAX_MESSAGE_SIZE + }); + throw new Error("Message too large"); + } + return true; + } +}; +var AtomicOperations = class { + constructor() { + this.locks = /* @__PURE__ */ new Map(); + } + async withLock(key, operation) { + if (this.locks.has(key)) { + await this.locks.get(key); + } + const lockPromise = (async () => { + try { + return await operation(); + } finally { + this.locks.delete(key); + } + })(); + this.locks.set(key, lockPromise); + return lockPromise; + } +}; +var RateLimiter = class { + constructor(maxRequests, windowMs) { + this.maxRequests = maxRequests; + this.windowMs = windowMs; + this.requests = /* @__PURE__ */ new Map(); + } + isAllowed(identifier) { + const now = Date.now(); + const windowStart = now - this.windowMs; + if (!this.requests.has(identifier)) { + this.requests.set(identifier, []); + } + const userRequests = this.requests.get(identifier); + const validRequests = userRequests.filter((time) => time > windowStart); + this.requests.set(identifier, validRequests); + if (validRequests.length >= this.maxRequests) { + SecurityErrorHandler.logSecurityEvent("rate_limit_exceeded", { + identifier, + requestCount: validRequests.length, + limit: this.maxRequests + }); + return false; + } + validRequests.push(now); + return true; + } +}; +var SecureMemoryManager = class { + static secureWipe(buffer) { + if (buffer instanceof ArrayBuffer) { + const view = new Uint8Array(buffer); + crypto.getRandomValues(view); + } else if (buffer instanceof Uint8Array) { + crypto.getRandomValues(buffer); + } + } + static secureDelete(obj, prop) { + if (obj[prop]) { + this.secureWipe(obj[prop]); + delete obj[prop]; + } + } +}; +var EnhancedSecureFileTransfer = class { + constructor(webrtcManager, onProgress, onComplete, onError, onFileReceived) { + this.webrtcManager = webrtcManager; + this.onProgress = onProgress; + this.onComplete = onComplete; + this.onError = onError; + this.onFileReceived = onFileReceived; + if (!webrtcManager) { + throw new Error("webrtcManager is required for EnhancedSecureFileTransfer"); + } + SecureFileTransferContext.getInstance().setFileTransferSystem(this); + this.atomicOps = new AtomicOperations(); + this.rateLimiter = new RateLimiter(10, 6e4); + this.signingKey = null; + this.verificationKey = null; + this.CHUNK_SIZE = 64 * 1024; + this.MAX_FILE_SIZE = 100 * 1024 * 1024; + this.MAX_CONCURRENT_TRANSFERS = 3; + this.CHUNK_TIMEOUT = 3e4; + this.RETRY_ATTEMPTS = 3; + this.FILE_TYPE_RESTRICTIONS = { + documents: { + extensions: [".pdf", ".doc", ".docx", ".txt", ".md", ".rtf", ".odt"], + mimeTypes: [ + "application/pdf", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "text/plain", + "text/markdown", + "application/rtf", + "application/vnd.oasis.opendocument.text" + ], + maxSize: 50 * 1024 * 1024, + // 50 MB + category: "Documents", + description: "PDF, DOC, TXT, MD, RTF, ODT" + }, + images: { + extensions: [".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg", ".ico"], + mimeTypes: [ + "image/jpeg", + "image/png", + "image/gif", + "image/webp", + "image/bmp", + "image/svg+xml", + "image/x-icon" + ], + maxSize: 25 * 1024 * 1024, + // 25 MB + category: "Images", + description: "JPG, PNG, GIF, WEBP, BMP, SVG, ICO" + }, + archives: { + extensions: [".zip", ".rar", ".7z", ".tar", ".gz", ".bz2", ".xz"], + mimeTypes: [ + "application/zip", + "application/x-rar-compressed", + "application/x-7z-compressed", + "application/x-tar", + "application/gzip", + "application/x-bzip2", + "application/x-xz" + ], + maxSize: 100 * 1024 * 1024, + // 100 MB + category: "Archives", + description: "ZIP, RAR, 7Z, TAR, GZ, BZ2, XZ" + }, + media: { + extensions: [".mp3", ".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm", ".ogg", ".wav"], + mimeTypes: [ + "audio/mpeg", + "video/mp4", + "video/x-msvideo", + "video/x-matroska", + "video/quicktime", + "video/x-ms-wmv", + "video/x-flv", + "video/webm", + "audio/ogg", + "audio/wav" + ], + maxSize: 100 * 1024 * 1024, + // 100 MB + category: "Media", + description: "MP3, MP4, AVI, MKV, MOV, WMV, FLV, WEBM, OGG, WAV" + }, + general: { + extensions: [], + mimeTypes: [], + maxSize: 50 * 1024 * 1024, + // 50 MB + category: "General", + description: "Any file type up to size limits" + } + }; + this.activeTransfers = /* @__PURE__ */ new Map(); + this.receivingTransfers = /* @__PURE__ */ new Map(); + this.transferQueue = []; + this.pendingChunks = /* @__PURE__ */ new Map(); + this.sessionKeys = /* @__PURE__ */ new Map(); + this.processedChunks = /* @__PURE__ */ new Set(); + this.transferNonces = /* @__PURE__ */ new Map(); + this.receivedFileBuffers = /* @__PURE__ */ new Map(); + this.setupFileMessageHandlers(); + if (this.webrtcManager) { + this.webrtcManager.fileTransferSystem = this; + } + } + // ============================================ + // FILE TYPE VALIDATION SYSTEM + // ============================================ + getFileType(file) { + const fileName = file.name.toLowerCase(); + const fileExtension = fileName.substring(fileName.lastIndexOf(".")); + const mimeType = file.type.toLowerCase(); + for (const [typeKey, typeConfig] of Object.entries(this.FILE_TYPE_RESTRICTIONS)) { + if (typeKey === "general") continue; + if (typeConfig.extensions.includes(fileExtension)) { + return { + type: typeKey, + category: typeConfig.category, + description: typeConfig.description, + maxSize: typeConfig.maxSize, + allowed: true + }; + } + if (typeConfig.mimeTypes.includes(mimeType)) { + return { + type: typeKey, + category: typeConfig.category, + description: typeConfig.description, + maxSize: typeConfig.maxSize, + allowed: true + }; + } + } + const generalConfig = this.FILE_TYPE_RESTRICTIONS.general; + return { + type: "general", + category: generalConfig.category, + description: generalConfig.description, + maxSize: generalConfig.maxSize, + allowed: true + }; + } + validateFile(file) { + const fileType = this.getFileType(file); + const errors = []; + if (file.size > fileType.maxSize) { + errors.push(`File size (${this.formatFileSize(file.size)}) exceeds maximum allowed for ${fileType.category} (${this.formatFileSize(fileType.maxSize)})`); + } + if (!fileType.allowed) { + errors.push(`File type not allowed. Supported types: ${fileType.description}`); + } + if (file.size > this.MAX_FILE_SIZE) { + errors.push(`File size (${this.formatFileSize(file.size)}) exceeds general limit (${this.formatFileSize(this.MAX_FILE_SIZE)})`); + } + return { + isValid: errors.length === 0, + errors, + fileType, + fileSize: file.size, + formattedSize: this.formatFileSize(file.size) + }; + } + formatFileSize(bytes) { + if (bytes === 0) return "0 B"; + const k = 1024; + const sizes = ["B", "KB", "MB", "GB"]; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; + } + getSupportedFileTypes() { + const supportedTypes = {}; + for (const [typeKey, typeConfig] of Object.entries(this.FILE_TYPE_RESTRICTIONS)) { + if (typeKey === "general") continue; + supportedTypes[typeKey] = { + category: typeConfig.category, + description: typeConfig.description, + extensions: typeConfig.extensions, + maxSize: this.formatFileSize(typeConfig.maxSize), + maxSizeBytes: typeConfig.maxSize + }; + } + return supportedTypes; + } + getFileTypeInfo() { + return { + supportedTypes: this.getSupportedFileTypes(), + generalMaxSize: this.formatFileSize(this.MAX_FILE_SIZE), + generalMaxSizeBytes: this.MAX_FILE_SIZE, + restrictions: this.FILE_TYPE_RESTRICTIONS + }; + } + // ============================================ + // ENCODING HELPERS (Base64 for efficient transport) + // ============================================ + arrayBufferToBase64(buffer) { + const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer); + let binary = ""; + const len = bytes.byteLength; + for (let i = 0; i < len; i++) { + binary += String.fromCharCode(bytes[i]); + } + return btoa(binary); + } + base64ToUint8Array(base64) { + const binaryString = atob(base64); + const len = binaryString.length; + const bytes = new Uint8Array(len); + for (let i = 0; i < len; i++) { + bytes[i] = binaryString.charCodeAt(i); + } + return bytes; + } + // ============================================ + // PUBLIC ACCESSORS FOR RECEIVED FILES + // ============================================ + getReceivedFileMeta(fileId) { + const entry = this.receivedFileBuffers.get(fileId); + if (!entry) return null; + return { fileId, fileName: entry.name, fileSize: entry.size, mimeType: entry.type }; + } + async getBlob(fileId) { + const entry = this.receivedFileBuffers.get(fileId); + if (!entry) return null; + return new Blob([entry.buffer], { type: entry.type }); + } + async getObjectURL(fileId) { + const blob = await this.getBlob(fileId); + if (!blob) return null; + return URL.createObjectURL(blob); + } + revokeObjectURL(url) { + try { + URL.revokeObjectURL(url); + } catch (_) { + } + } + setupFileMessageHandlers() { + if (!this.webrtcManager.dataChannel) { + const setupRetry = setInterval(() => { + if (this.webrtcManager.dataChannel) { + clearInterval(setupRetry); + this.setupMessageInterception(); + } + }, 100); + setTimeout(() => { + clearInterval(setupRetry); + }, 5e3); + return; + } + this.setupMessageInterception(); + } + setupMessageInterception() { + try { + if (!this.webrtcManager.dataChannel) { + return; + } + if (this.webrtcManager) { + this.webrtcManager.fileTransferSystem = this; + } + if (this.webrtcManager.dataChannel.onmessage) { + this.originalOnMessage = this.webrtcManager.dataChannel.onmessage; + } + this.webrtcManager.dataChannel.onmessage = async (event) => { + try { + if (event.data.length > MessageSizeValidator.MAX_MESSAGE_SIZE) { + console.warn("\u{1F512} Message too large, ignoring"); + SecurityErrorHandler.logSecurityEvent("oversized_message_blocked"); + return; + } + if (typeof event.data === "string") { + try { + const parsed = JSON.parse(event.data); + MessageSizeValidator.isMessageSizeValid(parsed); + if (this.isFileTransferMessage(parsed)) { + await this.handleFileMessage(parsed); + return; + } + } catch (parseError) { + if (parseError.message === "Message too large") { + return; + } + } + } + if (this.originalOnMessage) { + return this.originalOnMessage.call(this.webrtcManager.dataChannel, event); + } + } catch (error) { + console.error("\u274C Error in file system message interception:", error); + if (this.originalOnMessage) { + return this.originalOnMessage.call(this.webrtcManager.dataChannel, event); + } + } + }; + } catch (error) { + console.error("\u274C Failed to set up message interception:", error); + } + } + isFileTransferMessage(message) { + if (!message || typeof message !== "object" || !message.type) { + return false; + } + const fileMessageTypes2 = [ + "file_transfer_start", + "file_transfer_response", + "file_chunk", + "chunk_confirmation", + "file_transfer_complete", + "file_transfer_error" + ]; + return fileMessageTypes2.includes(message.type); + } + async handleFileMessage(message) { + try { + if (!this.webrtcManager.fileTransferSystem) { + try { + if (typeof this.webrtcManager.initializeFileTransfer === "function") { + this.webrtcManager.initializeFileTransfer(); + let attempts2 = 0; + const maxAttempts = 50; + while (!this.webrtcManager.fileTransferSystem && attempts2 < maxAttempts) { + await new Promise((resolve) => setTimeout(resolve, 100)); + attempts2++; + } + if (!this.webrtcManager.fileTransferSystem) { + throw new Error("File transfer system initialization timeout"); + } + } else { + throw new Error("initializeFileTransfer method not available"); + } + } catch (initError) { + console.error("\u274C Failed to initialize file transfer system:", initError); + if (message.fileId) { + const errorMessage = { + type: "file_transfer_error", + fileId: message.fileId, + error: "File transfer system not available", + timestamp: Date.now() + }; + await this.sendSecureMessage(errorMessage); + } + return; + } + } + switch (message.type) { + case "file_transfer_start": + await this.handleFileTransferStart(message); + break; + case "file_transfer_response": + this.handleTransferResponse(message); + break; + case "file_chunk": + await this.handleFileChunk(message); + break; + case "chunk_confirmation": + this.handleChunkConfirmation(message); + break; + case "file_transfer_complete": + this.handleTransferComplete(message); + break; + case "file_transfer_error": + this.handleTransferError(message); + break; + default: + console.warn("\u26A0\uFE0F Unknown file message type:", message.type); + } + } catch (error) { + console.error("\u274C Error handling file message:", error); + if (message.fileId) { + const errorMessage = { + type: "file_transfer_error", + fileId: message.fileId, + error: error.message, + timestamp: Date.now() + }; + await this.sendSecureMessage(errorMessage); + } + } + } + // ============================================ + // SIMPLIFIED KEY DERIVATION - USE SHARED DATA + // ============================================ + async deriveFileSessionKey(fileId) { + try { + if (!this.webrtcManager.keyFingerprint || !this.webrtcManager.sessionSalt) { + throw new Error("WebRTC session data not available"); + } + const fileSalt = crypto.getRandomValues(new Uint8Array(32)); + const encoder = new TextEncoder(); + const fingerprintData = encoder.encode(this.webrtcManager.keyFingerprint); + const fileIdData = encoder.encode(fileId); + const sessionSaltArray = new Uint8Array(this.webrtcManager.sessionSalt); + const combinedSeed = new Uint8Array( + fingerprintData.length + sessionSaltArray.length + fileSalt.length + fileIdData.length + ); + let offset = 0; + combinedSeed.set(fingerprintData, offset); + offset += fingerprintData.length; + combinedSeed.set(sessionSaltArray, offset); + offset += sessionSaltArray.length; + combinedSeed.set(fileSalt, offset); + offset += fileSalt.length; + combinedSeed.set(fileIdData, offset); + const keyMaterial = await crypto.subtle.digest("SHA-256", combinedSeed); + const fileSessionKey = await crypto.subtle.importKey( + "raw", + keyMaterial, + { name: "AES-GCM" }, + false, + ["encrypt", "decrypt"] + ); + this.sessionKeys.set(fileId, { + key: fileSessionKey, + salt: Array.from(fileSalt), + created: Date.now() + }); + return { key: fileSessionKey, salt: Array.from(fileSalt) }; + } catch (error) { + console.error("\u274C Failed to derive file session key:", error); + throw error; + } + } + async deriveFileSessionKeyFromSalt(fileId, saltArray) { + try { + if (!saltArray || !Array.isArray(saltArray) || saltArray.length !== 32) { + throw new Error(`Invalid salt: ${saltArray?.length || 0} bytes`); + } + if (!this.webrtcManager.keyFingerprint || !this.webrtcManager.sessionSalt) { + throw new Error("WebRTC session data not available"); + } + const encoder = new TextEncoder(); + const fingerprintData = encoder.encode(this.webrtcManager.keyFingerprint); + const fileIdData = encoder.encode(fileId); + const fileSalt = new Uint8Array(saltArray); + const sessionSaltArray = new Uint8Array(this.webrtcManager.sessionSalt); + const combinedSeed = new Uint8Array( + fingerprintData.length + sessionSaltArray.length + fileSalt.length + fileIdData.length + ); + let offset = 0; + combinedSeed.set(fingerprintData, offset); + offset += fingerprintData.length; + combinedSeed.set(sessionSaltArray, offset); + offset += sessionSaltArray.length; + combinedSeed.set(fileSalt, offset); + offset += fileSalt.length; + combinedSeed.set(fileIdData, offset); + const keyMaterial = await crypto.subtle.digest("SHA-256", combinedSeed); + const fileSessionKey = await crypto.subtle.importKey( + "raw", + keyMaterial, + { name: "AES-GCM" }, + false, + ["encrypt", "decrypt"] + ); + this.sessionKeys.set(fileId, { + key: fileSessionKey, + salt: saltArray, + created: Date.now() + }); + return fileSessionKey; + } catch (error) { + console.error("\u274C Failed to derive session key from salt:", error); + throw error; + } + } + // ============================================ + // FILE TRANSFER IMPLEMENTATION + // ============================================ + async sendFile(file) { + try { + if (!this.webrtcManager) { + throw new Error("WebRTC Manager not initialized"); + } + const clientId = this.getClientIdentifier(); + if (!this.rateLimiter.isAllowed(clientId)) { + SecurityErrorHandler.logSecurityEvent("rate_limit_exceeded", { clientId }); + throw new Error("Rate limit exceeded. Please wait before sending another file."); + } + if (!file || !file.size) { + throw new Error("Invalid file object"); + } + const validation = this.validateFile(file); + if (!validation.isValid) { + const errorMessage = validation.errors.join(". "); + throw new Error(errorMessage); + } + if (this.activeTransfers.size >= this.MAX_CONCURRENT_TRANSFERS) { + throw new Error("Maximum concurrent transfers reached"); + } + const fileId = `file_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + const fileHash = await this.calculateFileHash(file); + const keyResult = await this.deriveFileSessionKey(fileId); + const sessionKey = keyResult.key; + const salt = keyResult.salt; + const transferState = { + fileId, + file, + fileHash, + sessionKey, + salt, + totalChunks: Math.ceil(file.size / this.CHUNK_SIZE), + sentChunks: 0, + confirmedChunks: 0, + startTime: Date.now(), + status: "preparing", + retryCount: 0, + lastChunkTime: Date.now() + }; + this.activeTransfers.set(fileId, transferState); + this.transferNonces.set(fileId, 0); + await this.sendFileMetadata(transferState); + await this.startChunkTransmission(transferState); + return fileId; + } catch (error) { + const safeError = SecurityErrorHandler.sanitizeError(error); + console.error("\u274C File sending failed:", safeError); + if (this.onError) this.onError(safeError); + throw new Error(safeError); + } + } + async sendFileMetadata(transferState) { + try { + const metadata = { + type: "file_transfer_start", + fileId: transferState.fileId, + fileName: transferState.file.name, + fileSize: transferState.file.size, + fileType: transferState.file.type || "application/octet-stream", + fileHash: transferState.fileHash, + totalChunks: transferState.totalChunks, + chunkSize: this.CHUNK_SIZE, + salt: transferState.salt, + timestamp: Date.now(), + version: "2.0" + }; + if (this.signingKey) { + try { + metadata.signature = await FileMetadataSigner.signFileMetadata(metadata, this.signingKey); + console.log("\u{1F512} File metadata signed successfully"); + } catch (signError) { + SecurityErrorHandler.logSecurityEvent("signature_failed", { + fileId: transferState.fileId, + error: signError.message + }); + } + } + await this.sendSecureMessage(metadata); + transferState.status = "metadata_sent"; + } catch (error) { + const safeError = SecurityErrorHandler.sanitizeError(error); + console.error("\u274C Failed to send file metadata:", safeError); + transferState.status = "failed"; + throw new Error(safeError); + } + } + async startChunkTransmission(transferState) { + try { + transferState.status = "transmitting"; + const file = transferState.file; + const totalChunks = transferState.totalChunks; + for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) { + const start2 = chunkIndex * this.CHUNK_SIZE; + const end = Math.min(start2 + this.CHUNK_SIZE, file.size); + const chunkData = await this.readFileChunk(file, start2, end); + await this.sendFileChunk(transferState, chunkIndex, chunkData); + transferState.sentChunks++; + const progress = Math.round(transferState.sentChunks / totalChunks * 95) + 5; + await this.waitForBackpressure(); + } + transferState.status = "waiting_confirmation"; + setTimeout(() => { + if (this.activeTransfers.has(transferState.fileId)) { + const state = this.activeTransfers.get(transferState.fileId); + if (state.status === "waiting_confirmation") { + this.cleanupTransfer(transferState.fileId); + } + } + }, 3e4); + } catch (error) { + const safeError = SecurityErrorHandler.sanitizeError(error); + console.error("\u274C Chunk transmission failed:", safeError); + transferState.status = "failed"; + throw new Error(safeError); + } + } + async readFileChunk(file, start2, end) { + try { + const blob = file.slice(start2, end); + return await blob.arrayBuffer(); + } catch (error) { + const safeError = SecurityErrorHandler.sanitizeError(error); + console.error("\u274C Failed to read file chunk:", safeError); + throw new Error(safeError); + } + } + async sendFileChunk(transferState, chunkIndex, chunkData) { + try { + const sessionKey = transferState.sessionKey; + const nonce = crypto.getRandomValues(new Uint8Array(12)); + const encryptedChunk = await crypto.subtle.encrypt( + { + name: "AES-GCM", + iv: nonce + }, + sessionKey, + chunkData + ); + const encryptedB64 = this.arrayBufferToBase64(new Uint8Array(encryptedChunk)); + const chunkMessage = { + type: "file_chunk", + fileId: transferState.fileId, + chunkIndex, + totalChunks: transferState.totalChunks, + nonce: Array.from(nonce), + encryptedDataB64: encryptedB64, + chunkSize: chunkData.byteLength, + timestamp: Date.now() + }; + await this.waitForBackpressure(); + await this.sendSecureMessage(chunkMessage); + } catch (error) { + const safeError = SecurityErrorHandler.sanitizeError(error); + console.error("\u274C Failed to send file chunk:", safeError); + throw new Error(safeError); + } + } + async sendSecureMessage(message) { + const messageString = JSON.stringify(message); + const dc = this.webrtcManager?.dataChannel; + const maxRetries = 10; + let attempt = 0; + const wait = (ms) => new Promise((r) => setTimeout(r, ms)); + while (true) { + try { + if (!dc || dc.readyState !== "open") { + throw new Error("Data channel not ready"); + } + await this.waitForBackpressure(); + dc.send(messageString); + return; + } catch (error) { + const msg = String(error?.message || ""); + const queueFull = msg.includes("send queue is full") || msg.includes("bufferedAmount"); + const opErr = error?.name === "OperationError"; + if ((queueFull || opErr) && attempt < maxRetries) { + attempt++; + await this.waitForBackpressure(); + await wait(Math.min(50 * attempt, 500)); + continue; + } + console.error("\u274C Failed to send secure message:", error); + throw error; + } + } + } + async waitForBackpressure() { + try { + const dc = this.webrtcManager?.dataChannel; + if (!dc) return; + if (typeof dc.bufferedAmountLowThreshold === "number") { + if (dc.bufferedAmount > dc.bufferedAmountLowThreshold) { + await new Promise((resolve) => { + const handler = () => { + dc.removeEventListener("bufferedamountlow", handler); + resolve(); + }; + dc.addEventListener("bufferedamountlow", handler, { once: true }); + }); + } + return; + } + const softLimit = 4 * 1024 * 1024; + while (dc.bufferedAmount > softLimit) { + await new Promise((r) => setTimeout(r, 20)); + } + } catch (_) { + } + } + async calculateFileHash(file) { + try { + const arrayBuffer = await file.arrayBuffer(); + const hashBuffer = await crypto.subtle.digest("SHA-256", arrayBuffer); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + return hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); + } catch (error) { + console.error("\u274C File hash calculation failed:", error); + throw error; + } + } + // ============================================ + // MESSAGE HANDLERS + // ============================================ + async handleFileTransferStart(metadata) { + try { + if (!metadata.fileId || !metadata.fileName || !metadata.fileSize) { + throw new Error("Invalid file transfer metadata"); + } + if (metadata.signature && this.verificationKey) { + try { + const isValid = await FileMetadataSigner.verifyFileMetadata( + metadata, + metadata.signature, + this.verificationKey + ); + if (!isValid) { + SecurityErrorHandler.logSecurityEvent("invalid_metadata_signature", { + fileId: metadata.fileId + }); + throw new Error("Invalid file metadata signature"); + } + console.log("\u{1F512} File metadata signature verified successfully"); + } catch (verifyError) { + SecurityErrorHandler.logSecurityEvent("verification_failed", { + fileId: metadata.fileId, + error: verifyError.message + }); + throw new Error("File metadata verification failed"); + } + } + if (this.receivingTransfers.has(metadata.fileId)) { + return; + } + const sessionKey = await this.deriveFileSessionKeyFromSalt( + metadata.fileId, + metadata.salt + ); + const receivingState = { + fileId: metadata.fileId, + fileName: metadata.fileName, + fileSize: metadata.fileSize, + fileType: metadata.fileType || "application/octet-stream", + fileHash: metadata.fileHash, + totalChunks: metadata.totalChunks, + chunkSize: metadata.chunkSize || this.CHUNK_SIZE, + sessionKey, + salt: metadata.salt, + receivedChunks: /* @__PURE__ */ new Map(), + receivedCount: 0, + startTime: Date.now(), + lastChunkTime: Date.now(), + status: "receiving" + }; + this.receivingTransfers.set(metadata.fileId, receivingState); + const response = { + type: "file_transfer_response", + fileId: metadata.fileId, + accepted: true, + timestamp: Date.now() + }; + await this.sendSecureMessage(response); + if (this.pendingChunks.has(metadata.fileId)) { + const bufferedChunks = this.pendingChunks.get(metadata.fileId); + for (const [chunkIndex, chunkMessage] of bufferedChunks.entries()) { + await this.handleFileChunk(chunkMessage); + } + this.pendingChunks.delete(metadata.fileId); + } + } catch (error) { + const safeError = SecurityErrorHandler.sanitizeError(error); + console.error("\u274C Failed to handle file transfer start:", safeError); + const errorResponse = { + type: "file_transfer_response", + fileId: metadata.fileId, + accepted: false, + error: safeError, + timestamp: Date.now() + }; + await this.sendSecureMessage(errorResponse); + } + } + async handleFileChunk(chunkMessage) { + return this.atomicOps.withLock( + `chunk-${chunkMessage.fileId}`, + async () => { + try { + let receivingState = this.receivingTransfers.get(chunkMessage.fileId); + if (!receivingState) { + if (!this.pendingChunks.has(chunkMessage.fileId)) { + this.pendingChunks.set(chunkMessage.fileId, /* @__PURE__ */ new Map()); + } + this.pendingChunks.get(chunkMessage.fileId).set(chunkMessage.chunkIndex, chunkMessage); + return; + } + receivingState.lastChunkTime = Date.now(); + if (receivingState.receivedChunks.has(chunkMessage.chunkIndex)) { + return; + } + if (chunkMessage.chunkIndex < 0 || chunkMessage.chunkIndex >= receivingState.totalChunks) { + throw new Error(`Invalid chunk index: ${chunkMessage.chunkIndex}`); + } + const nonce = new Uint8Array(chunkMessage.nonce); + let encryptedData; + if (chunkMessage.encryptedDataB64) { + encryptedData = this.base64ToUint8Array(chunkMessage.encryptedDataB64); + } else if (chunkMessage.encryptedData) { + encryptedData = new Uint8Array(chunkMessage.encryptedData); + } else { + throw new Error("Missing encrypted data"); + } + const decryptedChunk = await crypto.subtle.decrypt( + { + name: "AES-GCM", + iv: nonce + }, + receivingState.sessionKey, + encryptedData + ); + if (decryptedChunk.byteLength !== chunkMessage.chunkSize) { + throw new Error(`Chunk size mismatch: expected ${chunkMessage.chunkSize}, got ${decryptedChunk.byteLength}`); + } + receivingState.receivedChunks.set(chunkMessage.chunkIndex, decryptedChunk); + receivingState.receivedCount++; + const confirmation = { + type: "chunk_confirmation", + fileId: chunkMessage.fileId, + chunkIndex: chunkMessage.chunkIndex, + timestamp: Date.now() + }; + await this.sendSecureMessage(confirmation); + if (receivingState.receivedCount === receivingState.totalChunks) { + await this.assembleFile(receivingState); + } + } catch (error) { + const safeError = SecurityErrorHandler.sanitizeError(error); + console.error("\u274C Failed to handle file chunk:", safeError); + const errorMessage = { + type: "file_transfer_error", + fileId: chunkMessage.fileId, + error: safeError, + chunkIndex: chunkMessage.chunkIndex, + timestamp: Date.now() + }; + await this.sendSecureMessage(errorMessage); + const receivingState = this.receivingTransfers.get(chunkMessage.fileId); + if (receivingState) { + receivingState.status = "failed"; + } + if (this.onError) { + this.onError(`Chunk processing failed: ${safeError}`); + } + } + } + ); + } + async assembleFile(receivingState) { + try { + receivingState.status = "assembling"; + for (let i = 0; i < receivingState.totalChunks; i++) { + if (!receivingState.receivedChunks.has(i)) { + throw new Error(`Missing chunk ${i}`); + } + } + const chunks = []; + for (let i = 0; i < receivingState.totalChunks; i++) { + const chunk = receivingState.receivedChunks.get(i); + chunks.push(new Uint8Array(chunk)); + } + const totalSize = chunks.reduce((sum, chunk) => sum + chunk.length, 0); + if (totalSize !== receivingState.fileSize) { + throw new Error(`File size mismatch: expected ${receivingState.fileSize}, got ${totalSize}`); + } + const fileData = new Uint8Array(totalSize); + let offset = 0; + for (const chunk of chunks) { + fileData.set(chunk, offset); + offset += chunk.length; + } + const receivedHash = await this.calculateFileHashFromData(fileData); + if (receivedHash !== receivingState.fileHash) { + throw new Error("File integrity check failed - hash mismatch"); + } + const fileBuffer = fileData.buffer; + const fileBlob = new Blob([fileBuffer], { type: receivingState.fileType }); + receivingState.endTime = Date.now(); + receivingState.status = "completed"; + this.receivedFileBuffers.set(receivingState.fileId, { + buffer: fileBuffer, + type: receivingState.fileType, + name: receivingState.fileName, + size: receivingState.fileSize + }); + if (this.onFileReceived) { + const getBlob = async () => new Blob([this.receivedFileBuffers.get(receivingState.fileId).buffer], { type: receivingState.fileType }); + const getObjectURL = async () => { + const blob = await getBlob(); + return URL.createObjectURL(blob); + }; + const revokeObjectURL = (url) => { + try { + URL.revokeObjectURL(url); + } catch (_) { + } + }; + this.onFileReceived({ + fileId: receivingState.fileId, + fileName: receivingState.fileName, + fileSize: receivingState.fileSize, + mimeType: receivingState.fileType, + transferTime: receivingState.endTime - receivingState.startTime, + // backward-compatibility for existing UIs + fileBlob, + getBlob, + getObjectURL, + revokeObjectURL + }); + } + const completionMessage = { + type: "file_transfer_complete", + fileId: receivingState.fileId, + success: true, + timestamp: Date.now() + }; + await this.sendSecureMessage(completionMessage); + if (this.receivingTransfers.has(receivingState.fileId)) { + const rs = this.receivingTransfers.get(receivingState.fileId); + if (rs && rs.receivedChunks) rs.receivedChunks.clear(); + } + this.receivingTransfers.delete(receivingState.fileId); + } catch (error) { + console.error("\u274C File assembly failed:", error); + receivingState.status = "failed"; + if (this.onError) { + this.onError(`File assembly failed: ${error.message}`); + } + const errorMessage = { + type: "file_transfer_complete", + fileId: receivingState.fileId, + success: false, + error: error.message, + timestamp: Date.now() + }; + await this.sendSecureMessage(errorMessage); + this.cleanupReceivingTransfer(receivingState.fileId); + } + } + async calculateFileHashFromData(data) { + try { + const hashBuffer = await crypto.subtle.digest("SHA-256", data); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + return hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); + } catch (error) { + console.error("\u274C Hash calculation failed:", error); + throw error; + } + } + handleTransferResponse(response) { + try { + const transferState = this.activeTransfers.get(response.fileId); + if (!transferState) { + return; + } + if (response.accepted) { + transferState.status = "accepted"; + } else { + transferState.status = "rejected"; + if (this.onError) { + this.onError(`Transfer rejected: ${response.error || "Unknown reason"}`); + } + this.cleanupTransfer(response.fileId); + } + } catch (error) { + console.error("\u274C Failed to handle transfer response:", error); + } + } + handleChunkConfirmation(confirmation) { + try { + const transferState = this.activeTransfers.get(confirmation.fileId); + if (!transferState) { + return; + } + transferState.confirmedChunks++; + transferState.lastChunkTime = Date.now(); + } catch (error) { + console.error("\u274C Failed to handle chunk confirmation:", error); + } + } + handleTransferComplete(completion) { + try { + const transferState = this.activeTransfers.get(completion.fileId); + if (!transferState) { + return; + } + if (completion.success) { + transferState.status = "completed"; + transferState.endTime = Date.now(); + if (this.onComplete) { + this.onComplete({ + fileId: transferState.fileId, + fileName: transferState.file.name, + fileSize: transferState.file.size, + transferTime: transferState.endTime - transferState.startTime, + status: "completed" + }); + } + } else { + transferState.status = "failed"; + if (this.onError) { + this.onError(`Transfer failed: ${completion.error || "Unknown error"}`); + } + } + this.cleanupTransfer(completion.fileId); + } catch (error) { + console.error("\u274C Failed to handle transfer completion:", error); + } + } + handleTransferError(errorMessage) { + try { + const transferState = this.activeTransfers.get(errorMessage.fileId); + if (transferState) { + transferState.status = "failed"; + this.cleanupTransfer(errorMessage.fileId); + } + const receivingState = this.receivingTransfers.get(errorMessage.fileId); + if (receivingState) { + receivingState.status = "failed"; + this.cleanupReceivingTransfer(errorMessage.fileId); + } + if (this.onError) { + this.onError(`Transfer error: ${errorMessage.error || "Unknown error"}`); + } + } catch (error) { + console.error("\u274C Failed to handle transfer error:", error); + } + } + // ============================================ + // UTILITY METHODS + // ============================================ + getActiveTransfers() { + return Array.from(this.activeTransfers.values()).map((transfer) => ({ + fileId: transfer.fileId, + fileName: transfer.file?.name || "Unknown", + fileSize: transfer.file?.size || 0, + progress: Math.round(transfer.sentChunks / transfer.totalChunks * 100), + status: transfer.status, + startTime: transfer.startTime + })); + } + getReceivingTransfers() { + return Array.from(this.receivingTransfers.values()).map((transfer) => ({ + fileId: transfer.fileId, + fileName: transfer.fileName || "Unknown", + fileSize: transfer.fileSize || 0, + progress: Math.round(transfer.receivedCount / transfer.totalChunks * 100), + status: transfer.status, + startTime: transfer.startTime + })); + } + cancelTransfer(fileId) { + try { + if (this.activeTransfers.has(fileId)) { + this.cleanupTransfer(fileId); + return true; + } + if (this.receivingTransfers.has(fileId)) { + this.cleanupReceivingTransfer(fileId); + return true; + } + return false; + } catch (error) { + console.error("\u274C Failed to cancel transfer:", error); + return false; + } + } + cleanupTransfer(fileId) { + this.activeTransfers.delete(fileId); + this.sessionKeys.delete(fileId); + this.transferNonces.delete(fileId); + for (const chunkId of this.processedChunks) { + if (chunkId.startsWith(fileId)) { + this.processedChunks.delete(chunkId); + } + } + } + // ✅ УЛУЧШЕННАЯ безопасная очистка памяти для предотвращения use-after-free + cleanupReceivingTransfer(fileId) { + try { + this.pendingChunks.delete(fileId); + const receivingState = this.receivingTransfers.get(fileId); + if (receivingState) { + if (receivingState.receivedChunks && receivingState.receivedChunks.size > 0) { + for (const [index, chunk] of receivingState.receivedChunks) { + try { + if (chunk && (chunk instanceof ArrayBuffer || chunk instanceof Uint8Array)) { + SecureMemoryManager.secureWipe(chunk); + if (chunk instanceof ArrayBuffer) { + const view = new Uint8Array(chunk); + view.fill(0); + } else if (chunk instanceof Uint8Array) { + chunk.fill(0); + } + } + } catch (chunkError) { + console.warn("\u26A0\uFE0F Failed to securely wipe chunk:", chunkError); + } + } + receivingState.receivedChunks.clear(); + } + if (receivingState.sessionKey) { + try { + receivingState.sessionKey = null; + } catch (keyError) { + console.warn("\u26A0\uFE0F Failed to clear session key:", keyError); + } + } + if (receivingState.salt) { + try { + if (Array.isArray(receivingState.salt)) { + receivingState.salt.fill(0); + } + receivingState.salt = null; + } catch (saltError) { + console.warn("\u26A0\uFE0F Failed to clear salt:", saltError); + } + } + for (const [key, value] of Object.entries(receivingState)) { + if (value && typeof value === "object") { + if (value instanceof ArrayBuffer || value instanceof Uint8Array) { + SecureMemoryManager.secureWipe(value); + } else if (Array.isArray(value)) { + value.fill(0); + } + receivingState[key] = null; + } + } + } + this.receivingTransfers.delete(fileId); + this.sessionKeys.delete(fileId); + const fileBuffer = this.receivedFileBuffers.get(fileId); + if (fileBuffer) { + try { + if (fileBuffer.buffer) { + SecureMemoryManager.secureWipe(fileBuffer.buffer); + const view = new Uint8Array(fileBuffer.buffer); + view.fill(0); + } + for (const [key, value] of Object.entries(fileBuffer)) { + if (value && typeof value === "object") { + if (value instanceof ArrayBuffer || value instanceof Uint8Array) { + SecureMemoryManager.secureWipe(value); + } + fileBuffer[key] = null; + } + } + this.receivedFileBuffers.delete(fileId); + } catch (bufferError) { + console.warn("\u26A0\uFE0F Failed to securely clear file buffer:", bufferError); + this.receivedFileBuffers.delete(fileId); + } + } + const chunksToRemove = []; + for (const chunkId of this.processedChunks) { + if (chunkId.startsWith(fileId)) { + chunksToRemove.push(chunkId); + } + } + for (const chunkId of chunksToRemove) { + this.processedChunks.delete(chunkId); + } + if (typeof global !== "undefined" && global.gc) { + try { + global.gc(); + } catch (gcError) { + } + } + console.log(`\u{1F512} Memory safely cleaned for file transfer: ${fileId}`); + } catch (error) { + console.error("\u274C Error during secure memory cleanup:", error); + this.receivingTransfers.delete(fileId); + this.sessionKeys.delete(fileId); + this.receivedFileBuffers.delete(fileId); + this.pendingChunks.delete(fileId); + throw new Error(`Memory cleanup failed: ${error.message}`); + } + } + getTransferStatus(fileId) { + if (this.activeTransfers.has(fileId)) { + const transfer = this.activeTransfers.get(fileId); + return { + type: "sending", + fileId: transfer.fileId, + fileName: transfer.file.name, + progress: Math.round(transfer.sentChunks / transfer.totalChunks * 100), + status: transfer.status, + startTime: transfer.startTime + }; + } + if (this.receivingTransfers.has(fileId)) { + const transfer = this.receivingTransfers.get(fileId); + return { + type: "receiving", + fileId: transfer.fileId, + fileName: transfer.fileName, + progress: Math.round(transfer.receivedCount / transfer.totalChunks * 100), + status: transfer.status, + startTime: transfer.startTime + }; + } + return null; + } + getSystemStatus() { + return { + initialized: true, + activeTransfers: this.activeTransfers.size, + receivingTransfers: this.receivingTransfers.size, + totalTransfers: this.activeTransfers.size + this.receivingTransfers.size, + maxConcurrentTransfers: this.MAX_CONCURRENT_TRANSFERS, + maxFileSize: this.MAX_FILE_SIZE, + chunkSize: this.CHUNK_SIZE, + hasWebrtcManager: !!this.webrtcManager, + isConnected: this.webrtcManager?.isConnected?.() || false, + hasDataChannel: !!this.webrtcManager?.dataChannel, + dataChannelState: this.webrtcManager?.dataChannel?.readyState, + isVerified: this.webrtcManager?.isVerified, + hasEncryptionKey: !!this.webrtcManager?.encryptionKey, + hasMacKey: !!this.webrtcManager?.macKey, + linkedToWebRTCManager: this.webrtcManager?.fileTransferSystem === this, + supportedFileTypes: this.getSupportedFileTypes(), + fileTypeInfo: this.getFileTypeInfo() + }; + } + cleanup() { + SecureFileTransferContext.getInstance().deactivate(); + if (this.webrtcManager && this.webrtcManager.dataChannel && this.originalOnMessage) { + this.webrtcManager.dataChannel.onmessage = this.originalOnMessage; + this.originalOnMessage = null; + } + if (this.webrtcManager && this.originalProcessMessage) { + this.webrtcManager.processMessage = this.originalProcessMessage; + this.originalProcessMessage = null; + } + if (this.webrtcManager && this.originalRemoveSecurityLayers) { + this.webrtcManager.removeSecurityLayers = this.originalRemoveSecurityLayers; + this.originalRemoveSecurityLayers = null; + } + for (const fileId of this.activeTransfers.keys()) { + this.cleanupTransfer(fileId); + } + for (const fileId of this.receivingTransfers.keys()) { + this.cleanupReceivingTransfer(fileId); + } + if (this.atomicOps) { + this.atomicOps.locks.clear(); + } + if (this.rateLimiter) { + this.rateLimiter.requests.clear(); + } + this.pendingChunks.clear(); + this.activeTransfers.clear(); + this.receivingTransfers.clear(); + this.transferQueue.length = 0; + this.sessionKeys.clear(); + this.transferNonces.clear(); + this.processedChunks.clear(); + this.clearKeys(); + } + // ============================================ + // SESSION UPDATE HANDLER - FIXED + // ============================================ + onSessionUpdate(sessionData) { + this.sessionKeys.clear(); + } + // ============================================ + // DEBUGGING AND DIAGNOSTICS + // ============================================ + diagnoseFileTransferIssue() { + const diagnosis = { + timestamp: (/* @__PURE__ */ new Date()).toISOString(), + fileTransferSystem: { + initialized: !!this, + hasWebrtcManager: !!this.webrtcManager, + webrtcManagerType: this.webrtcManager?.constructor?.name, + linkedToWebRTCManager: this.webrtcManager?.fileTransferSystem === this + }, + webrtcManager: { + hasDataChannel: !!this.webrtcManager?.dataChannel, + dataChannelState: this.webrtcManager?.dataChannel?.readyState, + isConnected: this.webrtcManager?.isConnected?.() || false, + isVerified: this.webrtcManager?.isVerified, + hasEncryptionKey: !!this.webrtcManager?.encryptionKey, + hasMacKey: !!this.webrtcManager?.macKey, + hasKeyFingerprint: !!this.webrtcManager?.keyFingerprint, + hasSessionSalt: !!this.webrtcManager?.sessionSalt + }, + securityContext: { + contextActive: SecureFileTransferContext.getInstance().isActive(), + securityLevel: SecureFileTransferContext.getInstance().getSecurityLevel(), + hasAtomicOps: !!this.atomicOps, + hasRateLimiter: !!this.rateLimiter + }, + transfers: { + activeTransfers: this.activeTransfers.size, + receivingTransfers: this.receivingTransfers.size, + pendingChunks: this.pendingChunks.size, + sessionKeys: this.sessionKeys.size + }, + fileTypeSupport: { + supportedTypes: this.getSupportedFileTypes(), + generalMaxSize: this.formatFileSize(this.MAX_FILE_SIZE), + restrictions: Object.keys(this.FILE_TYPE_RESTRICTIONS) + } + }; + return diagnosis; + } + async debugKeyDerivation(fileId) { + try { + if (!this.webrtcManager.keyFingerprint || !this.webrtcManager.sessionSalt) { + throw new Error("Session data not available"); + } + const senderResult = await this.deriveFileSessionKey(fileId); + const receiverKey = await this.deriveFileSessionKeyFromSalt(fileId, senderResult.salt); + const testData = new TextEncoder().encode("test data"); + const nonce = crypto.getRandomValues(new Uint8Array(12)); + const encrypted = await crypto.subtle.encrypt( + { name: "AES-GCM", iv: nonce }, + senderResult.key, + testData + ); + const decrypted = await crypto.subtle.decrypt( + { name: "AES-GCM", iv: nonce }, + receiverKey, + encrypted + ); + const decryptedText = new TextDecoder().decode(decrypted); + if (decryptedText === "test data") { + return { success: true, message: "All tests passed" }; + } else { + throw new Error("Decryption verification failed"); + } + } catch (error) { + console.error("\u274C Key derivation test failed:", error); + return { success: false, error: error.message }; + } + } + // ============================================ + // ALTERNATIVE METHOD OF INITIALIZING HANDLERS + // ============================================ + registerWithWebRTCManager() { + if (!this.webrtcManager) { + throw new Error("WebRTC manager not available"); + } + this.webrtcManager.fileTransferSystem = this; + this.webrtcManager.setFileMessageHandler = (handler) => { + this.webrtcManager._fileMessageHandler = handler; + }; + this.webrtcManager.setFileMessageHandler((message) => { + return this.handleFileMessage(message); + }); + } + static createFileMessageFilter(fileTransferSystem) { + return async (event) => { + try { + if (typeof event.data === "string") { + const parsed = JSON.parse(event.data); + if (fileTransferSystem.isFileTransferMessage(parsed)) { + await fileTransferSystem.handleFileMessage(parsed); + return true; + } + } + } catch (error) { + } + return false; + }; + } + // ============================================ + // SECURITY KEY MANAGEMENT + // ============================================ + setSigningKey(privateKey) { + if (!privateKey || !(privateKey instanceof CryptoKey)) { + throw new Error("Invalid private key for signing"); + } + this.signingKey = privateKey; + console.log("\u{1F512} Signing key set successfully"); + } + setVerificationKey(publicKey) { + if (!publicKey || !(publicKey instanceof CryptoKey)) { + throw new Error("Invalid public key for verification"); + } + this.verificationKey = publicKey; + console.log("\u{1F512} Verification key set successfully"); + } + async generateSigningKeyPair() { + try { + const keyPair = await crypto.subtle.generateKey( + { + name: "RSASSA-PKCS1-v1_5", + modulusLength: 2048, + publicExponent: new Uint8Array([1, 0, 1]), + hash: "SHA-256" + }, + true, + // extractable + ["sign", "verify"] + ); + this.signingKey = keyPair.privateKey; + this.verificationKey = keyPair.publicKey; + console.log("\u{1F512} RSA key pair generated successfully"); + return keyPair; + } catch (error) { + const safeError = SecurityErrorHandler.sanitizeError(error); + console.error("\u274C Failed to generate signing key pair:", safeError); + throw new Error(safeError); + } + } + clearKeys() { + this.signingKey = null; + this.verificationKey = null; + console.log("\u{1F512} Security keys cleared"); + } + getSecurityStatus() { + return { + signingEnabled: this.signingKey !== null, + verificationEnabled: this.verificationKey !== null, + contextActive: SecureFileTransferContext.getInstance().isActive(), + securityLevel: SecureFileTransferContext.getInstance().getSecurityLevel() + }; + } + getClientIdentifier() { + return this.webrtcManager?.connectionId || this.webrtcManager?.keyFingerprint?.substring(0, 16) || "default-client"; + } + destroy() { + SecureFileTransferContext.getInstance().deactivate(); + this.clearKeys(); + console.log("\u{1F512} File transfer system destroyed safely"); + } +}; + +// src/network/EnhancedSecureWebRTCManager.js +var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { + // ============================================ + // CONSTANTS + // ============================================ + static TIMEOUTS = { + KEY_ROTATION_INTERVAL: 3e5, + // 5 minutes + CONNECTION_TIMEOUT: 1e4, + // 10 seconds + HEARTBEAT_INTERVAL: 3e4, + // 30 seconds + SECURITY_CALC_DELAY: 1e3, + // 1 second + SECURITY_CALC_RETRY_DELAY: 3e3, + // 3 seconds + CLEANUP_INTERVAL: 3e5, + // 5 minutes (periodic cleanup) + CLEANUP_CHECK_INTERVAL: 6e4, + // 1 minute (cleanup check) + ICE_GATHERING_TIMEOUT: 1e4, + // 10 seconds + DISCONNECT_CLEANUP_DELAY: 500, + // 500ms + PEER_DISCONNECT_CLEANUP: 2e3, + // 2 seconds + STAGE2_ACTIVATION_DELAY: 1e4, + // 10 seconds + STAGE3_ACTIVATION_DELAY: 15e3, + // 15 seconds + STAGE4_ACTIVATION_DELAY: 2e4, + // 20 seconds + FILE_TRANSFER_INIT_DELAY: 1e3, + // 1 second + FAKE_TRAFFIC_MIN_INTERVAL: 15e3, + // 15 seconds + FAKE_TRAFFIC_MAX_INTERVAL: 3e4, + // 30 seconds + DECOY_INITIAL_DELAY: 5e3, + // 5 seconds + DECOY_TRAFFIC_MIN: 1e4, + // 10 seconds + DECOY_TRAFFIC_MAX: 25e3, + // 25 seconds + REORDER_TIMEOUT: 3e3, + // 3 seconds + RETRY_CONNECTION_DELAY: 2e3 + // 2 seconds + }; + static LIMITS = { + MAX_CONNECTION_ATTEMPTS: 3, + MAX_OLD_KEYS: 3, + MAX_PROCESSED_MESSAGE_IDS: 1e3, + MAX_OUT_OF_ORDER_PACKETS: 5, + MAX_DECOY_CHANNELS: 1, + MESSAGE_RATE_LIMIT: 60, + // messages per minute + MAX_KEY_AGE: 9e5, + // 15 minutes + OFFER_MAX_AGE: 36e5, + // 1 hour + SALT_SIZE_V3: 32, + // bytes + SALT_SIZE_V4: 64 + // bytes + }; + static SIZES = { + VERIFICATION_CODE_MIN_LENGTH: 6, + FAKE_TRAFFIC_MIN_SIZE: 32, + FAKE_TRAFFIC_MAX_SIZE: 128, + PACKET_PADDING_MIN: 64, + PACKET_PADDING_MAX: 512, + CHUNK_SIZE_MAX: 2048, + CHUNK_DELAY_MIN: 100, + CHUNK_DELAY_MAX: 500, + FINGERPRINT_DISPLAY_LENGTH: 8, + SESSION_ID_LENGTH: 16, + NESTED_ENCRYPTION_IV_SIZE: 12 + }; + static MESSAGE_TYPES = { + // Regular messages + MESSAGE: "message", + ENHANCED_MESSAGE: "enhanced_message", + // System messages + HEARTBEAT: "heartbeat", + VERIFICATION: "verification", + VERIFICATION_RESPONSE: "verification_response", + VERIFICATION_CONFIRMED: "verification_confirmed", + VERIFICATION_BOTH_CONFIRMED: "verification_both_confirmed", + PEER_DISCONNECT: "peer_disconnect", + SECURITY_UPGRADE: "security_upgrade", + KEY_ROTATION_SIGNAL: "key_rotation_signal", + KEY_ROTATION_READY: "key_rotation_ready", + // File transfer messages + FILE_TRANSFER_START: "file_transfer_start", + FILE_TRANSFER_RESPONSE: "file_transfer_response", + FILE_CHUNK: "file_chunk", + CHUNK_CONFIRMATION: "chunk_confirmation", + FILE_TRANSFER_COMPLETE: "file_transfer_complete", + FILE_TRANSFER_ERROR: "file_transfer_error", + // Fake traffic + FAKE: "fake" + }; + static FILTERED_RESULTS = { + FAKE_MESSAGE: "FAKE_MESSAGE_FILTERED", + FILE_MESSAGE: "FILE_MESSAGE_FILTERED", + SYSTEM_MESSAGE: "SYSTEM_MESSAGE_FILTERED" + }; + // Static debug flag instead of this._debugMode + static DEBUG_MODE = false; + // Set to true during development, false in production + constructor(onMessage, onStatusChange, onKeyExchange, onVerificationRequired, onAnswerError = null, onVerificationStateChange = null, config = {}) { + this._isProductionMode = this._detectProductionMode(); + this._debugMode = !this._isProductionMode && _EnhancedSecureWebRTCManager.DEBUG_MODE; + this._config = { + fakeTraffic: { + enabled: config.fakeTraffic?.enabled ?? true, + minInterval: config.fakeTraffic?.minInterval ?? _EnhancedSecureWebRTCManager.TIMEOUTS.FAKE_TRAFFIC_MIN_INTERVAL, + maxInterval: config.fakeTraffic?.maxInterval ?? _EnhancedSecureWebRTCManager.TIMEOUTS.FAKE_TRAFFIC_MAX_INTERVAL, + minSize: config.fakeTraffic?.minSize ?? _EnhancedSecureWebRTCManager.SIZES.FAKE_TRAFFIC_MIN_SIZE, + maxSize: config.fakeTraffic?.maxSize ?? _EnhancedSecureWebRTCManager.SIZES.FAKE_TRAFFIC_MAX_SIZE, + patterns: config.fakeTraffic?.patterns ?? ["heartbeat", "status", "sync"] + }, + decoyChannels: { + enabled: config.decoyChannels?.enabled ?? true, + maxDecoyChannels: config.decoyChannels?.maxDecoyChannels ?? _EnhancedSecureWebRTCManager.LIMITS.MAX_DECOY_CHANNELS, + decoyChannelNames: config.decoyChannels?.decoyChannelNames ?? ["heartbeat"], + sendDecoyData: config.decoyChannels?.sendDecoyData ?? true, + randomDecoyIntervals: config.decoyChannels?.randomDecoyIntervals ?? true + }, + packetPadding: { + enabled: config.packetPadding?.enabled ?? true, + minPadding: config.packetPadding?.minPadding ?? _EnhancedSecureWebRTCManager.SIZES.PACKET_PADDING_MIN, + maxPadding: config.packetPadding?.maxPadding ?? _EnhancedSecureWebRTCManager.SIZES.PACKET_PADDING_MAX, + useRandomPadding: config.packetPadding?.useRandomPadding ?? true, + preserveMessageSize: config.packetPadding?.preserveMessageSize ?? false + }, + antiFingerprinting: { + enabled: config.antiFingerprinting?.enabled ?? false, + randomizeTiming: config.antiFingerprinting?.randomizeTiming ?? true, + randomizeSizes: config.antiFingerprinting?.randomizeSizes ?? false, + addNoise: config.antiFingerprinting?.addNoise ?? true, + maskPatterns: config.antiFingerprinting?.maskPatterns ?? false, + useRandomHeaders: config.antiFingerprinting?.useRandomHeaders ?? false + } + }; + this._initializeSecureLogging(); + this._setupOwnLogger(); + this._setupProductionLogging(); + this._storeImportantMethods(); + this._setupSecureGlobalAPI(); + if (!window.EnhancedSecureCryptoUtils) { + throw new Error("EnhancedSecureCryptoUtils is not loaded. Please ensure the module is loaded first."); + } + this.getSecurityData = () => { + return this.lastSecurityCalculation ? { + level: this.lastSecurityCalculation.level, + score: this.lastSecurityCalculation.score, + timestamp: this.lastSecurityCalculation.timestamp + // Do NOT return check details or sensitive data + } : null; + }; + this._secureLog("info", "\u{1F512} Enhanced WebRTC Manager initialized with secure API"); + this.currentSessionType = null; + this.currentSecurityLevel = "basic"; + this.sessionConstraints = null; + this.peerConnection = null; + this.dataChannel = null; + this.onMessage = onMessage; + this.onStatusChange = onStatusChange; + this.onKeyExchange = onKeyExchange; + this.onVerificationStateChange = onVerificationStateChange; + this.onVerificationRequired = onVerificationRequired; + this.onAnswerError = onAnswerError; + this.isInitiator = false; + this.connectionAttempts = 0; + this.maxConnectionAttempts = _EnhancedSecureWebRTCManager.LIMITS.MAX_CONNECTION_ATTEMPTS; + try { + this._initializeMutexSystem(); + } catch (error) { + this._secureLog("error", "\u274C Failed to initialize mutex system", { + errorType: error.constructor.name + }); + throw new Error("Critical: Mutex system initialization failed"); + } + if (!this._validateMutexSystem()) { + this._secureLog("error", "\u274C Mutex system validation failed after initialization"); + throw new Error("Critical: Mutex system validation failed"); + } + if (typeof window !== "undefined") { + this._secureLog("info", "\u{1F512} Emergency mutex handlers will be available through secure API"); + } + this._secureLog("info", "\u{1F512} Enhanced Mutex system fully initialized and validated"); + this.heartbeatInterval = null; + this.messageQueue = []; + this.ecdhKeyPair = null; + this.ecdsaKeyPair = null; + if (this.fileTransferSystem) { + this.fileTransferSystem.cleanup(); + this.fileTransferSystem = null; + } + this.verificationCode = null; + this.pendingSASCode = null; + this.isVerified = false; + this.processedMessageIds = /* @__PURE__ */ new Set(); + this.localVerificationConfirmed = false; + this.remoteVerificationConfirmed = false; + this.bothVerificationsConfirmed = false; + this.expectedDTLSFingerprint = null; + this.strictDTLSValidation = true; + this.ephemeralKeyPairs = /* @__PURE__ */ new Map(); + this.sessionStartTime = Date.now(); + this.messageCounter = 0; + this.sequenceNumber = 0; + this.expectedSequenceNumber = 0; + this.sessionSalt = null; + this.replayWindowSize = 64; + this.replayWindow = /* @__PURE__ */ new Set(); + this.maxSequenceGap = 100; + this.replayProtectionEnabled = true; + this.sessionId = null; + this.connectionId = Array.from(crypto.getRandomValues(new Uint8Array(8))).map((b) => b.toString(16).padStart(2, "0")).join(""); + this.peerPublicKey = null; + this.rateLimiterId = null; + this.intentionalDisconnect = false; + this.lastCleanupTime = Date.now(); + this._resetNotificationFlags(); + this.verificationInitiationSent = false; + this.disconnectNotificationSent = false; + this.reconnectionFailedNotificationSent = false; + this.peerDisconnectNotificationSent = false; + this.connectionClosedNotificationSent = false; + this.fakeTrafficDisabledNotificationSent = false; + this.advancedFeaturesDisabledNotificationSent = false; + this.securityUpgradeNotificationSent = false; + this.lastSecurityUpgradeStage = null; + this.securityCalculationNotificationSent = false; + this.lastSecurityCalculationLevel = null; + this.fileTransferSystem = null; + this.onFileProgress = null; + this._ivTrackingSystem = { + usedIVs: /* @__PURE__ */ new Set(), + // Track all used IVs to prevent reuse + ivHistory: /* @__PURE__ */ new Map(), + // Track IV usage with timestamps (max 10k entries) + collisionCount: 0, + // Track potential collisions + maxIVHistorySize: 1e4, + // Maximum IV history size + maxSessionIVs: 1e3, + // Maximum IVs per session + entropyValidation: { + minEntropy: 3, + // Minimum entropy threshold + entropyTests: 0, + entropyFailures: 0 + }, + rngValidation: { + testsPerformed: 0, + weakRngDetected: false, + lastValidation: 0 + }, + sessionIVs: /* @__PURE__ */ new Map(), + // Track IVs per session + emergencyMode: false + // Emergency mode if IV reuse detected + }; + this._lastIVCleanupTime = null; + this._secureErrorHandler = { + errorCategories: { + CRYPTOGRAPHIC: "cryptographic", + NETWORK: "network", + VALIDATION: "validation", + SYSTEM: "system", + UNKNOWN: "unknown" + }, + errorMappings: /* @__PURE__ */ new Map(), + // Map internal errors to safe messages + errorCounts: /* @__PURE__ */ new Map(), + // Track error frequencies + lastErrorTime: 0, + errorThreshold: 10, + // Max errors per minute + isInErrorMode: false + }; + this._secureMemoryManager = { + sensitiveData: /* @__PURE__ */ new WeakMap(), + // Track sensitive data for secure cleanup + cleanupQueue: [], + // Queue for deferred cleanup operations + isCleaning: false, + // Prevent concurrent cleanup operations + cleanupInterval: null, + // Periodic cleanup timer + memoryStats: { + totalCleanups: 0, + failedCleanups: 0, + lastCleanup: 0 + } + }; + this.onFileReceived = null; + this.onFileError = null; + this.keyRotationInterval = _EnhancedSecureWebRTCManager.TIMEOUTS.KEY_ROTATION_INTERVAL; + this.lastKeyRotation = Date.now(); + this.currentKeyVersion = 0; + this.keyVersions = /* @__PURE__ */ new Map(); + this.oldKeys = /* @__PURE__ */ new Map(); + this.maxOldKeys = _EnhancedSecureWebRTCManager.LIMITS.MAX_OLD_KEYS; + this.peerConnection = null; + this.dataChannel = null; + this.securityFeatures = { + hasEncryption: true, + hasECDH: true, + hasECDSA: false, + hasMutualAuth: false, + hasMetadataProtection: false, + hasEnhancedReplayProtection: false, + hasNonExtractableKeys: false, + hasRateLimiting: true, + hasEnhancedValidation: false, + hasPFS: true, + // Real Perfect Forward Secrecy enabled + // Advanced Features (Session Managed) + hasNestedEncryption: false, + hasPacketPadding: false, + hasPacketReordering: false, + hasAntiFingerprinting: false, + hasFakeTraffic: false, + hasDecoyChannels: false, + hasMessageChunking: false + }; + this._secureLog("info", "\u{1F512} Enhanced WebRTC Manager initialized with tiered security"); + this._secureLog("info", "\u{1F512} Configuration loaded from constructor parameters", { + fakeTraffic: this._config.fakeTraffic.enabled, + decoyChannels: this._config.decoyChannels.enabled, + packetPadding: this._config.packetPadding.enabled, + antiFingerprinting: this._config.antiFingerprinting.enabled + }); + this._hardenDebugModeReferences(); + this._initializeUnifiedScheduler(); + this._syncSecurityFeaturesWithTariff(); + if (!this._validateCryptographicSecurity()) { + this._secureLog("error", "\u{1F6A8} CRITICAL: Cryptographic security validation failed after tariff sync"); + throw new Error("Critical cryptographic features are missing after tariff synchronization"); + } + this.nestedEncryptionKey = null; + this.paddingConfig = { + enabled: this._config.packetPadding.enabled, + minPadding: this._config.packetPadding.minPadding, + maxPadding: this._config.packetPadding.maxPadding, + useRandomPadding: this._config.packetPadding.useRandomPadding, + preserveMessageSize: this._config.packetPadding.preserveMessageSize + }; + this.fakeTrafficConfig = { + enabled: this._config.fakeTraffic.enabled, + minInterval: this._config.fakeTraffic.minInterval, + maxInterval: this._config.fakeTraffic.maxInterval, + minSize: this._config.fakeTraffic.minSize, + maxSize: this._config.fakeTraffic.maxSize, + patterns: this._config.fakeTraffic.patterns + }; + this.fakeTrafficTimer = null; + this.lastFakeTraffic = 0; + this.chunkingConfig = { + enabled: false, + maxChunkSize: _EnhancedSecureWebRTCManager.SIZES.CHUNK_SIZE_MAX, + minDelay: _EnhancedSecureWebRTCManager.SIZES.CHUNK_DELAY_MIN, + maxDelay: _EnhancedSecureWebRTCManager.SIZES.CHUNK_DELAY_MAX, + useRandomDelays: true, + addChunkHeaders: true + }; + this.chunkQueue = []; + this.chunkingInProgress = false; + this.decoyChannels = /* @__PURE__ */ new Map(); + this.decoyChannelConfig = { + enabled: this._config.decoyChannels.enabled, + maxDecoyChannels: this._config.decoyChannels.maxDecoyChannels, + decoyChannelNames: this._config.decoyChannels.decoyChannelNames, + sendDecoyData: this._config.decoyChannels.sendDecoyData, + randomDecoyIntervals: this._config.decoyChannels.randomDecoyIntervals + }; + this.decoyTimers = /* @__PURE__ */ new Map(); + this.reorderingConfig = { + enabled: false, + maxOutOfOrder: _EnhancedSecureWebRTCManager.LIMITS.MAX_OUT_OF_ORDER_PACKETS, + reorderTimeout: _EnhancedSecureWebRTCManager.TIMEOUTS.REORDER_TIMEOUT, + useSequenceNumbers: true, + useTimestamps: true + }; + this.packetBuffer = /* @__PURE__ */ new Map(); + this.lastProcessedSequence = -1; + this.antiFingerprintingConfig = { + enabled: this._config.antiFingerprinting.enabled, + randomizeTiming: this._config.antiFingerprinting.randomizeTiming, + randomizeSizes: this._config.antiFingerprinting.randomizeSizes, + addNoise: this._config.antiFingerprinting.addNoise, + maskPatterns: this._config.antiFingerprinting.maskPatterns, + useRandomHeaders: this._config.antiFingerprinting.useRandomHeaders + }; + this.fingerprintMask = this.generateFingerprintMask(); + this.rateLimiterId = `webrtc_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + this.startPeriodicCleanup(); + this.initializeEnhancedSecurity(); + this._keyOperationMutex = { + locked: false, + queue: [], + lockId: null, + lockTimeout: null + }; + this._cryptoOperationMutex = { + locked: false, + queue: [], + lockId: null, + lockTimeout: null + }; + this._connectionOperationMutex = { + locked: false, + queue: [], + lockId: null, + lockTimeout: null + }; + this._keySystemState = { + isInitializing: false, + isRotating: false, + isDestroying: false, + lastOperation: null, + lastOperationTime: Date.now() + }; + this._operationCounters = { + keyOperations: 0, + cryptoOperations: 0, + connectionOperations: 0 + }; + } + /** + * Create AAD with sequence number for anti-replay protection + * This binds each message to its sequence number and prevents replay attacks + */ + _createMessageAAD(messageType, messageData = null, isFileMessage = false) { + try { + const aad = { + sessionId: this.currentSession?.sessionId || this.sessionId || "unknown", + keyFingerprint: this.keyFingerprint || "unknown", + sequenceNumber: this._generateNextSequenceNumber(), + messageType, + timestamp: Date.now(), + connectionId: this.connectionId || "unknown", + isFileMessage + }; + if (messageData && typeof messageData === "object") { + if (messageData.fileId) aad.fileId = messageData.fileId; + if (messageData.chunkIndex !== void 0) aad.chunkIndex = messageData.chunkIndex; + if (messageData.totalChunks !== void 0) aad.totalChunks = messageData.totalChunks; + } + return JSON.stringify(aad); + } catch (error) { + this._secureLog("error", "\u274C Failed to create message AAD", { + errorType: error.constructor.name, + message: error.message, + messageType + }); + return JSON.stringify({ + sessionId: "unknown", + keyFingerprint: "unknown", + sequenceNumber: Date.now(), + messageType, + timestamp: Date.now(), + connectionId: "unknown", + isFileMessage + }); + } + } + /** + * Generate next sequence number for outgoing messages + * This ensures unique ordering and prevents replay attacks + */ + _generateNextSequenceNumber() { + const nextSeq = this.sequenceNumber++; + if (this.sequenceNumber > Number.MAX_SAFE_INTEGER - 1e3) { + this.sequenceNumber = 0; + this.expectedSequenceNumber = 0; + this.replayWindow.clear(); + this._secureLog("warn", "\u26A0\uFE0F Sequence number reset due to overflow", { + timestamp: Date.now() + }); + } + return nextSeq; + } + /** + * Enhanced mutex system initialization with atomic protection + */ + _initializeMutexSystem() { + this._keyOperationMutex = { + locked: false, + queue: [], + lockId: null, + lockTimeout: null, + lockTime: null, + operationCount: 0 + }; + this._cryptoOperationMutex = { + locked: false, + queue: [], + lockId: null, + lockTimeout: null, + lockTime: null, + operationCount: 0 + }; + this._connectionOperationMutex = { + locked: false, + queue: [], + lockId: null, + lockTimeout: null, + lockTime: null, + operationCount: 0 + }; + this._keySystemState = { + isInitializing: false, + isRotating: false, + isDestroying: false, + lastOperation: null, + lastOperationTime: Date.now(), + operationId: null, + concurrentOperations: 0, + maxConcurrentOperations: 1 + }; + this._operationCounters = { + keyOperations: 0, + cryptoOperations: 0, + connectionOperations: 0, + totalOperations: 0, + failedOperations: 0 + }; + this._secureLog("info", "\u{1F512} Enhanced mutex system initialized with atomic protection", { + mutexes: ["keyOperation", "cryptoOperation", "connectionOperation"], + timestamp: Date.now(), + features: ["atomic_operations", "race_condition_protection", "enhanced_state_tracking"] + }); + } + /** + * XSS Hardening - Debug mode references validation + * This method is called during initialization to ensure XSS hardening + */ + _hardenDebugModeReferences() { + this._secureLog("info", "\u{1F512} XSS Hardening: Debug mode references already replaced"); + } + /** + * Unified scheduler for all maintenance tasks + * Replaces multiple setInterval calls with a single, controlled scheduler + */ + _initializeUnifiedScheduler() { + this._maintenanceScheduler = setInterval(() => { + this._executeMaintenanceCycle(); + }, 3e5); + this._secureLog("info", "\u{1F527} Unified maintenance scheduler initialized (5-minute cycle)"); + this._activeTimers = /* @__PURE__ */ new Set([this._maintenanceScheduler]); + } + /** + * Execute all maintenance tasks in a single cycle + */ + _executeMaintenanceCycle() { + try { + this._secureLog("info", "\u{1F527} Starting maintenance cycle"); + this._cleanupLogs(); + this._auditLoggingSystemSecurity(); + this._verifyAPIIntegrity(); + this._validateCryptographicSecurity(); + this._syncSecurityFeaturesWithTariff(); + this._cleanupResources(); + this._enforceResourceLimits(); + if (this.isConnected && this.isVerified) { + this._monitorKeySecurity(); + } + if (this._debugMode) { + this._monitorGlobalExposure(); + } + if (this._heartbeatConfig && this._heartbeatConfig.enabled && this.isConnected()) { + this._sendHeartbeat(); + } + this._secureLog("info", "\u{1F527} Maintenance cycle completed successfully"); + } catch (error) { + this._secureLog("error", "\u274C Maintenance cycle failed", { + errorType: error?.constructor?.name || "Unknown", + message: error?.message || "Unknown error" + }); + this._emergencyCleanup(); + } + } + /** + * Enforce hard resource limits with emergency cleanup + */ + _enforceResourceLimits() { + const violations = []; + if (this._logCounts.size > this._resourceLimits.maxLogEntries) { + violations.push("log_entries"); + } + if (this.messageQueue.length > this._resourceLimits.maxMessageQueue) { + violations.push("message_queue"); + } + if (this._ivTrackingSystem && this._ivTrackingSystem.ivHistory.size > this._resourceLimits.maxIVHistory) { + violations.push("iv_history"); + } + if (this.processedMessageIds.size > this._resourceLimits.maxProcessedMessageIds) { + violations.push("processed_message_ids"); + } + if (this.decoyChannels.size > this._resourceLimits.maxDecoyChannels) { + violations.push("decoy_channels"); + } + if (this._fakeTrafficMessages && this._fakeTrafficMessages.length > this._resourceLimits.maxFakeTrafficMessages) { + violations.push("fake_traffic_messages"); + } + if (this.chunkQueue.length > this._resourceLimits.maxChunkQueue) { + violations.push("chunk_queue"); + } + if (this.packetBuffer && this.packetBuffer.size > this._resourceLimits.maxPacketBuffer) { + violations.push("packet_buffer"); + } + if (violations.length > 0) { + this._secureLog("warn", "\u26A0\uFE0F Resource limit violations detected", { violations }); + this._emergencyCleanup(); + } + } + /** + * Emergency cleanup when resource limits are exceeded + */ + _emergencyCleanup() { + this._secureLog("warn", "\u{1F6A8} EMERGENCY: Resource limits exceeded, performing emergency cleanup"); + try { + this._logCounts.clear(); + this._secureLog("info", "\u{1F9F9} Emergency: All logs cleared"); + this.messageQueue.length = 0; + this._secureLog("info", "\u{1F9F9} Emergency: Message queue cleared"); + if (this._ivTrackingSystem) { + this._ivTrackingSystem.usedIVs.clear(); + this._ivTrackingSystem.ivHistory.clear(); + this._ivTrackingSystem.sessionIVs.clear(); + this._ivTrackingSystem.collisionCount = 0; + this._ivTrackingSystem.emergencyMode = false; + this._secureLog("info", "\u{1F9F9} Enhanced Emergency: IV tracking system cleared"); + } + this.processedMessageIds.clear(); + this._secureLog("info", "\u{1F9F9} Emergency: Processed message IDs cleared"); + if (this.decoyChannels) { + for (const [channelName, timer] of this.decoyTimers) { + if (timer) clearTimeout(timer); + } + this.decoyChannels.clear(); + this.decoyTimers.clear(); + this._secureLog("info", "\u{1F9F9} Enhanced Emergency: Decoy channels cleared"); + } + if (this.fakeTrafficTimer) { + clearTimeout(this.fakeTrafficTimer); + this.fakeTrafficTimer = null; + } + if (this._fakeTrafficMessages) { + this._fakeTrafficMessages.length = 0; + this._secureLog("info", "\u{1F9F9} Enhanced Emergency: Fake traffic messages cleared"); + } + this.chunkQueue.length = 0; + this._secureLog("info", "\u{1F9F9} Emergency: Chunk queue cleared"); + if (this.packetBuffer) { + this.packetBuffer.clear(); + this._secureLog("info", "\u{1F9F9} Emergency: Packet buffer cleared"); + } + this._secureMemoryManager.isCleaning = true; + this._secureMemoryManager.cleanupQueue.length = 0; + this._secureMemoryManager.memoryStats.lastCleanup = Date.now(); + if (typeof window.gc === "function") { + try { + for (let i = 0; i < 3; i++) { + window.gc(); + this._secureLog("info", `\u{1F9F9} Enhanced Emergency: Garbage collection cycle ${i + 1}/3`); + if (i < 2) { + const start2 = Date.now(); + while (Date.now() - start2 < 10) { + } + } + } + } catch (e) { + } + } + this._secureMemoryManager.isCleaning = false; + this._secureLog("info", "\u2705 Enhanced emergency cleanup completed successfully"); + } catch (error) { + this._secureLog("error", "\u274C Enhanced emergency cleanup failed", { + errorType: error?.constructor?.name || "Unknown", + message: error?.message || "Unknown error" + }); + this._secureMemoryManager.isCleaning = false; + } + } + /** + * Validate emergency cleanup success + * @param {Object} originalState - Original state before cleanup + * @returns {Object} Validation results + */ + _validateEmergencyCleanup(originalState) { + const currentState = { + messageQueueSize: this.messageQueue.length, + processedIdsSize: this.processedMessageIds.size, + packetBufferSize: this.packetBuffer ? this.packetBuffer.size : 0, + ivTrackingSize: this._ivTrackingSystem ? this._ivTrackingSystem.usedIVs.size : 0, + decoyChannelsSize: this.decoyChannels ? this.decoyChannels.size : 0 + }; + const validation = { + messageQueueCleared: currentState.messageQueueSize === 0, + processedIdsCleared: currentState.processedIdsSize === 0, + packetBufferCleared: currentState.packetBufferSize === 0, + ivTrackingCleared: currentState.ivTrackingSize === 0, + decoyChannelsCleared: currentState.decoyChannelsSize === 0, + allCleared: currentState.messageQueueSize === 0 && currentState.processedIdsSize === 0 && currentState.packetBufferSize === 0 && currentState.ivTrackingSize === 0 && currentState.decoyChannelsSize === 0 + }; + return validation; + } + /** + * Cleanup resources based on age and usage + */ + _cleanupResources() { + const now = Date.now(); + if (this.processedMessageIds.size > this._emergencyThresholds.processedMessageIds) { + this.processedMessageIds.clear(); + this._secureLog("info", "\u{1F9F9} Old processed message IDs cleared"); + } + if (this._ivTrackingSystem) { + this._cleanupOldIVs(); + } + this.cleanupOldKeys(); + if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureCryptoUtils.rateLimiter) { + window.EnhancedSecureCryptoUtils.rateLimiter.cleanup(); + } + this._secureLog("info", "\u{1F9F9} Resource cleanup completed"); + } + /** + * Monitor key security (replaces _startKeySecurityMonitoring) + */ + _monitorKeySecurity() { + if (this._keyStorageStats.activeKeys > 10) { + this._secureLog("warn", "\u26A0\uFE0F High number of active keys detected. Consider rotation."); + } + if (Date.now() - (this._keyStorageStats.lastRotation || 0) > 36e5) { + this._rotateKeys(); + } + } + /** + * Send heartbeat message (called by unified scheduler) + */ + _sendHeartbeat() { + try { + if (this.isConnected() && this.dataChannel && this.dataChannel.readyState === "open") { + this.dataChannel.send(JSON.stringify({ + type: _EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT, + timestamp: Date.now() + })); + this._heartbeatConfig.lastHeartbeat = Date.now(); + this._secureLog("debug", "\u{1F493} Heartbeat sent"); + } + } catch (error) { + this._secureLog("error", "\u274C Heartbeat failed:", { + errorType: error?.constructor?.name || "Unknown", + message: error?.message || "Unknown error" + }); + } + } + /** + * Comprehensive input validation to prevent DoS and injection attacks + * @param {any} data - Data to validate + * @param {string} context - Context for validation (e.g., 'sendMessage', 'sendSecureMessage') + * @returns {Object} Validation result with isValid and sanitizedData + */ + _validateInputData(data, context = "unknown") { + const validationResult = { + isValid: false, + sanitizedData: null, + errors: [], + warnings: [] + }; + try { + if (data === null || data === void 0) { + validationResult.errors.push("Data cannot be null or undefined"); + return validationResult; + } + if (typeof data === "string") { + if (data.length > this._inputValidationLimits.maxStringLength) { + validationResult.errors.push(`String too long: ${data.length} > ${this._inputValidationLimits.maxStringLength}`); + return validationResult; + } + for (const pattern of this._maliciousPatterns) { + if (pattern.test(data)) { + validationResult.errors.push(`Malicious pattern detected: ${pattern.source}`); + this._secureLog("warn", "\u{1F6A8} Malicious pattern detected in input", { + context, + pattern: pattern.source, + dataLength: data.length + }); + return validationResult; + } + } + validationResult.sanitizedData = this._sanitizeInputString(data); + validationResult.isValid = true; + return validationResult; + } + if (typeof data === "object") { + const seen = /* @__PURE__ */ new WeakSet(); + const checkCircular = (obj, path = "") => { + if (obj === null || typeof obj !== "object") return; + if (seen.has(obj)) { + validationResult.errors.push(`Circular reference detected at path: ${path}`); + return; + } + seen.add(obj); + if (path.split(".").length > this._inputValidationLimits.maxObjectDepth) { + validationResult.errors.push(`Object too deep: ${path.split(".").length} > ${this._inputValidationLimits.maxObjectDepth}`); + return; + } + if (Array.isArray(obj) && obj.length > this._inputValidationLimits.maxArrayLength) { + validationResult.errors.push(`Array too long: ${obj.length} > ${this._inputValidationLimits.maxArrayLength}`); + return; + } + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + checkCircular(obj[key], path ? `${path}.${key}` : key); + } + } + }; + checkCircular(data); + if (validationResult.errors.length > 0) { + return validationResult; + } + const objectSize = this._calculateObjectSize(data); + if (objectSize > this._inputValidationLimits.maxMessageSize) { + validationResult.errors.push(`Object too large: ${objectSize} bytes > ${this._inputValidationLimits.maxMessageSize} bytes`); + return validationResult; + } + validationResult.sanitizedData = this._sanitizeInputObject(data); + validationResult.isValid = true; + return validationResult; + } + if (data instanceof ArrayBuffer) { + if (data.byteLength > this._inputValidationLimits.maxMessageSize) { + validationResult.errors.push(`ArrayBuffer too large: ${data.byteLength} bytes > ${this._inputValidationLimits.maxMessageSize} bytes`); + return validationResult; + } + validationResult.sanitizedData = data; + validationResult.isValid = true; + return validationResult; + } + validationResult.errors.push(`Unsupported data type: ${typeof data}`); + return validationResult; + } catch (error) { + validationResult.errors.push(`Validation error: ${error.message}`); + this._secureLog("error", "\u274C Input validation failed", { + context, + errorType: error?.constructor?.name || "Unknown", + message: error?.message || "Unknown error" + }); + return validationResult; + } + } + /** + * Calculate approximate object size in bytes + * @param {any} obj - Object to calculate size for + * @returns {number} Size in bytes + */ + _calculateObjectSize(obj) { + try { + const jsonString = JSON.stringify(obj); + return new TextEncoder().encode(jsonString).length; + } catch (error) { + return 1024 * 1024; + } + } + /** + * Sanitize string data for input validation + * @param {string} str - String to sanitize + * @returns {string} Sanitized string + */ + _sanitizeInputString(str) { + if (typeof str !== "string") return str; + str = str.replace(/\0/g, ""); + str = str.replace(/\s+/g, " "); + str = str.trim(); + return str; + } + /** + * Sanitize object data for input validation + * @param {any} obj - Object to sanitize + * @returns {any} Sanitized object + */ + _sanitizeInputObject(obj) { + if (obj === null || typeof obj !== "object") return obj; + if (Array.isArray(obj)) { + return obj.map((item) => this._sanitizeInputObject(item)); + } + const sanitized = {}; + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + const value = obj[key]; + if (typeof value === "string") { + sanitized[key] = this._sanitizeInputString(value); + } else if (typeof value === "object") { + sanitized[key] = this._sanitizeInputObject(value); + } else { + sanitized[key] = value; + } + } + } + return sanitized; + } + /** + * Rate limiting for message sending + * @param {string} context - Context for rate limiting + * @returns {boolean} true if rate limit allows + */ + _checkRateLimit(context = "message") { + const now = Date.now(); + if (!this._rateLimiter) { + this._rateLimiter = { + messageCount: 0, + lastReset: now, + burstCount: 0, + lastBurstReset: now + }; + } + if (now - this._rateLimiter.lastReset > 6e4) { + this._rateLimiter.messageCount = 0; + this._rateLimiter.lastReset = now; + } + if (now - this._rateLimiter.lastBurstReset > 1e3) { + this._rateLimiter.burstCount = 0; + this._rateLimiter.lastBurstReset = now; + } + if (this._rateLimiter.burstCount >= this._inputValidationLimits.rateLimitBurstSize) { + this._secureLog("warn", "\u26A0\uFE0F Rate limit burst exceeded", { context }); + return false; + } + if (this._rateLimiter.messageCount >= this._inputValidationLimits.rateLimitMessagesPerMinute) { + this._secureLog("warn", "\u26A0\uFE0F Rate limit exceeded", { context }); + return false; + } + this._rateLimiter.messageCount++; + this._rateLimiter.burstCount++; + return true; + } + // ============================================ + // SECURE KEY STORAGE MANAGEMENT + // ============================================ + /** + * Initializes the secure key storage + */ + _initializeSecureKeyStorage() { + this._secureKeyStorage = new SecureKeyStorage(); + this._keyStorageStats = { + totalKeys: 0, + activeKeys: 0, + lastAccess: null, + lastRotation: null + }; + this._secureLog("info", "\u{1F510} Enhanced secure key storage initialized"); + } + // Helper: ensure file transfer system is ready (lazy init on receiver) + async _ensureFileTransferReady() { + try { + if (this.fileTransferSystem) { + return true; + } + if (!this.dataChannel || this.dataChannel.readyState !== "open") { + throw new Error("Data channel not open"); + } + if (!this.isVerified) { + throw new Error("Connection not verified"); + } + this.initializeFileTransfer(); + let attempts2 = 0; + const maxAttempts = 50; + while (!this.fileTransferSystem && attempts2 < maxAttempts) { + await new Promise((r) => setTimeout(r, 100)); + attempts2++; + } + if (!this.fileTransferSystem) { + throw new Error("File transfer system initialization timeout"); + } + return true; + } catch (e) { + this._secureLog("error", "\u274C _ensureFileTransferReady failed", { + errorType: e?.constructor?.name || "Unknown", + hasMessage: !!e?.message + }); + return false; + } + } + _getSecureKey(keyId) { + return this._secureKeyStorage.retrieveKey(keyId); + } + async _setSecureKey(keyId, key) { + if (!(key instanceof CryptoKey)) { + this._secureLog("error", "\u274C Attempt to store non-CryptoKey"); + return false; + } + const success = await this._secureKeyStorage.storeKey(keyId, key, { + version: this.currentKeyVersion, + type: key.algorithm.name + }); + if (success) { + this._secureLog("info", `\u{1F511} Key ${keyId} stored securely with encryption`); + } + return success; + } + /** + * Validates a key value + * @param {CryptoKey} key - Key to validate + * @returns {boolean} true if the key is valid + */ + _validateKeyValue(key) { + return key instanceof CryptoKey && key.algorithm && key.usages && key.usages.length > 0; + } + _secureWipeKeys() { + this._secureKeyStorage.secureWipeAll(); + this._secureLog("info", "\u{1F9F9} All keys securely wiped and encrypted storage cleared"); + } + /** + * Validates key storage state + * @returns {boolean} true if the storage is ready + */ + _validateKeyStorage() { + return this._secureKeyStorage instanceof SecureKeyStorage; + } + /** + * Returns secure key storage statistics + * @returns {object} Storage metrics + */ + _getKeyStorageStats() { + const stats = this._secureKeyStorage.getStorageStats(); + return { + totalKeysCount: stats.totalKeys, + activeKeysCount: stats.totalKeys, + hasLastAccess: stats.metadata.some((m) => m.lastAccessed), + hasLastRotation: !!this._keyStorageStats.lastRotation, + storageType: "SecureKeyStorage", + timestamp: Date.now() + }; + } + /** + * Performs key rotation in storage + */ + _rotateKeys() { + const oldKeys = Array.from(this._secureKeyStorage.keys()); + this._secureKeyStorage.clear(); + this._keyStorageStats.lastRotation = Date.now(); + this._keyStorageStats.activeKeys = 0; + this._secureLog("info", `\u{1F504} Key rotation completed. ${oldKeys.length} keys rotated`); + } + /** + * Emergency key wipe (e.g., upon detecting a threat) + */ + _emergencyKeyWipe() { + this._secureWipeKeys(); + this._secureLog("error", "\u{1F6A8} EMERGENCY: All keys wiped due to security threat"); + } + /** + * Starts key security monitoring + * @deprecated Use unified scheduler instead + */ + _startKeySecurityMonitoring() { + this._secureLog("info", "\u{1F527} Key security monitoring moved to unified scheduler"); + } + // ============================================ + // HELPER METHODS + // ============================================ + /** + * Constant-time key validation to prevent timing attacks + * @param {CryptoKey} key - Key to validate + * @returns {boolean} true if key is valid + */ + _validateKeyConstantTime(key) { + let isValid = 0; + try { + const isCryptoKey = key instanceof CryptoKey; + isValid += isCryptoKey ? 1 : 0; + } catch { + isValid += 0; + } + try { + const hasAlgorithm = !!(key && key.algorithm); + isValid += hasAlgorithm ? 1 : 0; + } catch { + isValid += 0; + } + try { + const hasType = !!(key && key.type); + isValid += hasType ? 1 : 0; + } catch { + isValid += 0; + } + try { + const hasExtractable = key && key.extractable !== void 0; + isValid += hasExtractable ? 1 : 0; + } catch { + isValid += 0; + } + return isValid === 4; + } + /** + * Constant-time key pair validation + * @param {Object} keyPair - Key pair to validate + * @returns {boolean} true if key pair is valid + */ + _validateKeyPairConstantTime(keyPair) { + if (!keyPair || typeof keyPair !== "object") return false; + const privateKeyValid = this._validateKeyConstantTime(keyPair.privateKey); + const publicKeyValid = this._validateKeyConstantTime(keyPair.publicKey); + return privateKeyValid && publicKeyValid; + } + /** + * Enhanced secure logging system initialization + */ + _initializeSecureLogging() { + this._logLevels = { + error: 0, + warn: 1, + info: 2, + debug: 3, + trace: 4 + }; + this._currentLogLevel = this._isProductionMode ? this._logLevels.error : ( + // In production, ONLY critical errors + this._logLevels.info + ); + this._logCounts = /* @__PURE__ */ new Map(); + this._maxLogCount = this._isProductionMode ? 5 : 50; + this._resourceLimits = { + maxLogEntries: this._isProductionMode ? 100 : 1e3, + maxMessageQueue: 1e3, + maxIVHistory: 1e4, + maxProcessedMessageIds: 5e3, + maxDecoyChannels: 100, + maxFakeTrafficMessages: 500, + maxChunkQueue: 200, + maxPacketBuffer: 1e3 + }; + this._emergencyThresholds = { + logEntries: this._resourceLimits.maxLogEntries * 0.8, + // 80% + messageQueue: this._resourceLimits.maxMessageQueue * 0.8, + ivHistory: this._resourceLimits.maxIVHistory * 0.8, + processedMessageIds: this._resourceLimits.maxProcessedMessageIds * 0.8 + }; + this._inputValidationLimits = { + maxStringLength: 1e5, + // 100KB for strings + maxObjectDepth: 10, + // Maximum object nesting depth + maxArrayLength: 1e3, + // Maximum array length + maxMessageSize: 1024 * 1024, + // 1MB total message size + maxConcurrentMessages: 10, + // Maximum concurrent message processing + rateLimitMessagesPerMinute: 60, + // Rate limiting + rateLimitBurstSize: 10 + // Burst size for rate limiting + }; + this._maliciousPatterns = [ + /)<[^<]*)*<\/script>/gi, + // Script tags + /javascript:/gi, + // JavaScript protocol + /data:text\/html/gi, + // Data URLs with HTML + /on\w+\s*=/gi, + // Event handlers + /eval\s*\(/gi, + // eval() calls + /document\./gi, + // Document object access + /window\./gi, + // Window object access + /localStorage/gi, + // LocalStorage access + /sessionStorage/gi, + // SessionStorage access + /fetch\s*\(/gi, + // Fetch API calls + /XMLHttpRequest/gi, + // XHR calls + /import\s*\(/gi, + // Dynamic imports + /require\s*\(/gi, + // Require calls + /process\./gi, + // Process object access + /global/gi, + // Global object access + /__proto__/gi, + // Prototype pollution + /constructor/gi, + // Constructor access + /prototype/gi, + // Prototype access + /toString\s*\(/gi, + // toString calls + /valueOf\s*\(/gi + // valueOf calls + ]; + this._absoluteBlacklist = /* @__PURE__ */ new Set([ + // Cryptographic keys + "encryptionKey", + "macKey", + "metadataKey", + "privateKey", + "publicKey", + "ecdhKeyPair", + "ecdsaKeyPair", + "peerPublicKey", + "nestedEncryptionKey", + // Authentication and session data + "verificationCode", + "sessionSalt", + "keyFingerprint", + "sessionId", + "authChallenge", + "authProof", + "authToken", + "sessionToken", + // Credentials and secrets + "password", + "token", + "secret", + "credential", + "signature", + "apiKey", + "accessKey", + "secretKey", + "privateKey", + // Cryptographic materials + "hash", + "digest", + "nonce", + "iv", + "cipher", + "seed", + "entropy", + "random", + "salt", + "fingerprint", + // JWT and session data + "jwt", + "bearer", + "refreshToken", + "accessToken", + // File transfer sensitive data + "fileHash", + "fileSignature", + "transferKey", + "chunkKey" + ]); + this._safeFieldsWhitelist = /* @__PURE__ */ new Set([ + // Basic status fields + "timestamp", + "type", + "status", + "state", + "level", + "isConnected", + "isVerified", + "isInitiator", + "version", + // Counters and metrics (safe) + "count", + "total", + "active", + "inactive", + "success", + "failure", + // Connection states (safe) + "readyState", + "connectionState", + "iceConnectionState", + // Feature counts (safe) + "activeFeaturesCount", + "totalFeatures", + "stage", + // Error types (safe) + "errorType", + "errorCode", + "phase", + "attempt" + ]); + this._initializeLogSecurityMonitoring(); + this._secureLog("info", `\u{1F527} Enhanced secure logging initialized (Production: ${this._isProductionMode})`); + } + /** + * Initialize security monitoring for logging system + */ + _initializeLogSecurityMonitoring() { + this._logSecurityViolations = 0; + this._maxLogSecurityViolations = 3; + } + /** + * Audit logging system security + */ + _auditLoggingSystemSecurity() { + let violations = 0; + for (const [key, count] of this._logCounts.entries()) { + if (count > this._maxLogCount * 2) { + violations++; + this._originalConsole?.error?.(`\u{1F6A8} LOG SECURITY: Excessive log count detected: ${key}`); + } + } + const recentLogs = Array.from(this._logCounts.keys()); + for (const logKey of recentLogs) { + if (this._containsSensitiveContent(logKey)) { + violations++; + this._originalConsole?.error?.(`\u{1F6A8} LOG SECURITY: Sensitive content in log key: ${logKey}`); + } + } + this._logSecurityViolations += violations; + if (this._logSecurityViolations >= this._maxLogSecurityViolations) { + this._emergencyDisableLogging(); + this._originalConsole?.error?.("\u{1F6A8} CRITICAL: Logging system disabled due to security violations"); + } + } + /** + * Shim to redirect arbitrary console.log calls to _secureLog('info', ...) + * Fixed syntax errors and improved error handling + */ + _secureLogShim(...args) { + try { + if (!Array.isArray(args) || args.length === 0) { + return; + } + const message = args[0]; + const restArgs = args.slice(1); + if (restArgs.length === 0) { + this._secureLog("info", String(message || "")); + return; + } + if (restArgs.length === 1) { + this._secureLog("info", String(message || ""), restArgs[0]); + return; + } + this._secureLog("info", String(message || ""), { + additionalArgs: restArgs, + argCount: restArgs.length + }); + } catch (error) { + try { + if (this._originalConsole?.log) { + this._originalConsole.log(...args); + } + } catch (fallbackError) { + } + } + } + /** + * Redirects global console.log to this instance's secure logger + * Improved error handling and validation + */ + /** + * Setup own logger without touching global console + */ + _setupOwnLogger() { + this.logger = { + log: (message, data) => this._secureLog("info", message, data), + info: (message, data) => this._secureLog("info", message, data), + warn: (message, data) => this._secureLog("warn", message, data), + error: (message, data) => this._secureLog("error", message, data), + debug: (message, data) => this._secureLog("debug", message, data) + }; + if (_EnhancedSecureWebRTCManager.DEBUG_MODE) { + this._secureLog("info", "\u{1F512} Own logger created - development mode"); + } else { + this._secureLog("info", "\u{1F512} Own logger created - production mode"); + } + } + /** + * Production logging - use own logger with minimal output + */ + _setupProductionLogging() { + if (this._isProductionMode) { + this.logger = { + log: () => { + }, + // No-op in production + info: () => { + }, + // No-op in production + warn: (message, data) => this._secureLog("warn", message, data), + error: (message, data) => this._secureLog("error", message, data), + debug: () => { + } + // No-op in production + }; + this._secureLog("info", "\u{1F512} Production logging mode activated"); + } + } + /** + * Secure logging with enhanced data protection + * @param {string} level - Log level (error, warn, info, debug, trace) + * @param {string} message - Message + * @param {object} data - Optional payload (will be sanitized) + */ + _secureLog(level, message, data = null) { + if (data && !this._auditLogMessage(message, data)) { + this._originalConsole?.error?.("\u{1F6A8} SECURITY: Logging blocked due to potential data leakage"); + return; + } + if (this._logLevels[level] > this._currentLogLevel) { + return; + } + const logKey = `${level}:${message.substring(0, 50)}`; + const currentCount = this._logCounts.get(logKey) || 0; + if (currentCount >= this._maxLogCount) { + return; + } + this._logCounts.set(logKey, currentCount + 1); + let sanitizedData = null; + if (data) { + sanitizedData = this._sanitizeLogData(data); + if (this._containsSensitiveContent(JSON.stringify(sanitizedData))) { + this._originalConsole?.error?.("\u{1F6A8} SECURITY: Sanitized data still contains sensitive content - blocking log"); + return; + } + } + if (this._isProductionMode) { + if (level === "error") { + const safeMessage = this._sanitizeString(message); + this._originalConsole?.error?.(safeMessage); + } + return; + } + const logMethod = this._originalConsole?.[level] || this._originalConsole?.log; + if (sanitizedData) { + logMethod(message, sanitizedData); + } else { + logMethod(message); + } + } + /** + * Enhanced sanitization for log data with multiple security layers + */ + _sanitizeLogData(data) { + if (typeof data === "string") { + return this._sanitizeString(data); + } + if (!data || typeof data !== "object") { + return data; + } + const sanitized = {}; + for (const [key, value] of Object.entries(data)) { + const lowerKey = key.toLowerCase(); + const blacklistPatterns = [ + "key", + "secret", + "token", + "password", + "credential", + "auth", + "fingerprint", + "salt", + "signature", + "private", + "encryption", + "mac", + "metadata", + "session", + "jwt", + "bearer", + "hash", + "digest", + "nonce", + "iv", + "cipher", + "seed", + "entropy" + ]; + const isBlacklisted = this._absoluteBlacklist.has(key) || blacklistPatterns.some((pattern) => lowerKey.includes(pattern)); + if (isBlacklisted) { + sanitized[key] = "[SENSITIVE_DATA_BLOCKED]"; + continue; + } + if (this._safeFieldsWhitelist.has(key)) { + if (typeof value === "string") { + sanitized[key] = this._sanitizeString(value); + } else { + sanitized[key] = value; + } + continue; + } + if (typeof value === "boolean" || typeof value === "number") { + sanitized[key] = value; + } else if (typeof value === "string") { + sanitized[key] = this._sanitizeString(value); + } else if (value instanceof ArrayBuffer || value instanceof Uint8Array) { + sanitized[key] = `[${value.constructor.name}( bytes)]`; + } else if (value && typeof value === "object") { + try { + sanitized[key] = this._sanitizeLogData(value); + } catch (error) { + sanitized[key] = "[RECURSIVE_SANITIZATION_FAILED]"; + } + } else { + sanitized[key] = `[${typeof value}]`; + } + } + const sanitizedString = JSON.stringify(sanitized); + if (this._containsSensitiveContent(sanitizedString)) { + return { error: "SANITIZATION_FAILED_SENSITIVE_CONTENT_DETECTED" }; + } + return sanitized; + } + /** + * Enhanced sanitization for strings with comprehensive pattern detection + */ + _sanitizeString(str) { + if (typeof str !== "string" || str.length === 0) { + return str; + } + const sensitivePatterns = [ + // Hex patterns (various lengths) + /[a-f0-9]{16,}/i, + // 16+ hex chars (covers short keys) + /[a-f0-9]{8,}/i, + // 8+ hex chars (covers shorter keys) + // Base64 patterns (comprehensive) + /[A-Za-z0-9+/]{16,}={0,2}/, + // Base64 with padding + /[A-Za-z0-9+/]{12,}/, + // Base64 without padding + /[A-Za-z0-9+/=]{10,}/, + // Base64-like patterns + // Base58 patterns (Bitcoin-style) + /[1-9A-HJ-NP-Za-km-z]{16,}/, + // Base58 strings + // Base32 patterns + /[A-Z2-7]{16,}={0,6}/, + // Base32 with padding + /[A-Z2-7]{12,}/, + // Base32 without padding + // Custom encoding patterns + /[A-Za-z0-9\-_]{16,}/, + // URL-safe base64 variants + /[A-Za-z0-9\.\-_]{16,}/, + // JWT-like patterns + // Long alphanumeric strings (potential keys) + /\b[A-Za-z0-9]{12,}\b/, + // 12+ alphanumeric chars + /\b[A-Za-z0-9]{8,}\b/, + // 8+ alphanumeric chars + // PEM key patterns + /BEGIN\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\s+KEY/i, + /END\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\s+KEY/i, + // JWT patterns + /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/, + // API key patterns + /(api[_-]?key|token|secret|password|credential)[\s]*[:=][\s]*[A-Za-z0-9\-_]{8,}/i, + // UUID patterns + /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i, + // Credit cards and SSN (existing patterns) + /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/, + /\b\d{3}-\d{2}-\d{4}\b/, + // Email patterns (more restrictive) + /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/, + // Crypto-specific patterns + /(fingerprint|hash|digest|signature)[\s]*[:=][\s]*[A-Za-z0-9\-_]{8,}/i, + /(encryption|mac|metadata)[\s]*key[\s]*[:=][\s]*[A-Za-z0-9\-_]{8,}/i, + // Session and auth patterns + /(session|auth|jwt|bearer)[\s]*[:=][\s]*[A-Za-z0-9\-_]{8,}/i + ]; + for (const pattern of sensitivePatterns) { + if (pattern.test(str)) { + return "[SENSITIVE_DATA_REDACTED]"; + } + } + if (this._hasHighEntropy(str)) { + return "[HIGH_ENTROPY_DATA_REDACTED]"; + } + if (this._hasSuspiciousDistribution(str)) { + return "[SUSPICIOUS_DATA_REDACTED]"; + } + if (str.length > 50) { + return str.substring(0, 20) + "...[TRUNCATED]"; + } + return str; + } + /** + * Enhanced sensitive content detection + */ + _containsSensitiveContent(str) { + if (typeof str !== "string") return false; + const sensitivePatterns = [ + /[a-f0-9]{16,}/i, + /[A-Za-z0-9+/]{16,}={0,2}/, + /[1-9A-HJ-NP-Za-km-z]{16,}/, + /[A-Z2-7]{16,}={0,6}/, + /\b[A-Za-z0-9]{12,}\b/, + /BEGIN\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\s+KEY/i, + /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/, + /(api[_-]?key|token|secret|password|credential)[\s]*[:=][\s]*[A-Za-z0-9\-_]{8,}/i + ]; + return sensitivePatterns.some((pattern) => pattern.test(str)) || this._hasHighEntropy(str) || this._hasSuspiciousDistribution(str); + } + /** + * Check for high entropy strings (likely cryptographic keys) + */ + _hasHighEntropy(str) { + if (str.length < 8) return false; + const charCount = {}; + for (const char of str) { + charCount[char] = (charCount[char] || 0) + 1; + } + const length = str.length; + let entropy = 0; + for (const count of Object.values(charCount)) { + const probability = count / length; + entropy -= probability * Math.log2(probability); + } + return entropy > 4.5; + } + /** + * Check for suspicious character distributions + */ + _hasSuspiciousDistribution(str) { + if (str.length < 8) return false; + const hexChars = str.match(/[a-f0-9]/gi) || []; + if (hexChars.length >= str.length * 0.8) { + return true; + } + const base64Chars = str.match(/[A-Za-z0-9+/=]/g) || []; + if (base64Chars.length >= str.length * 0.9) { + return true; + } + const uniqueChars = new Set(str).size; + const diversityRatio = uniqueChars / str.length; + if (diversityRatio > 0.8 && str.length > 16) { + return true; + } + return false; + } + // ============================================ + // SECURE LOGGING SYSTEM + // ============================================ + /** + * Detects production mode + */ + _detectProductionMode() { + return ( + // Standard env variables + typeof process !== "undefined" && false || // No debug flags + !this._debugMode || // Production domains + window.location.hostname && !window.location.hostname.includes("localhost") && !window.location.hostname.includes("127.0.0.1") && !window.location.hostname.includes(".local") || // Minified code (heuristic check) + typeof window.webpackHotUpdate === "undefined" && !window.location.search.includes("debug") + ); + } + // ============================================ + // FIXED SECURE GLOBAL API + // ============================================ + /** + * Sets up a secure global API with limited access + */ + _setupSecureGlobalAPI() { + this._secureLog("info", "\u{1F512} Starting secure global API setup"); + const secureAPI = {}; + if (typeof this.sendMessage === "function") { + secureAPI.sendMessage = this.sendMessage.bind(this); + } + secureAPI.getConnectionStatus = () => ({ + isConnected: this.isConnected ? this.isConnected() : false, + isVerified: this.isVerified || false, + connectionState: this.peerConnection?.connectionState || "disconnected" + }); + secureAPI.getSecurityStatus = () => ({ + securityLevel: this.currentSecurityLevel || "basic", + stage: "initialized", + activeFeaturesCount: Object.values(this.securityFeatures || {}).filter(Boolean).length + }); + if (typeof this.sendFile === "function") { + secureAPI.sendFile = this.sendFile.bind(this); + } + secureAPI.getFileTransferStatus = () => ({ + initialized: !!this.fileTransferSystem, + status: "ready", + activeTransfers: 0, + receivingTransfers: 0 + }); + if (typeof this.disconnect === "function") { + secureAPI.disconnect = this.disconnect.bind(this); + } + const safeGlobalAPI = { + ...secureAPI, + // Spread only existing methods + getConfiguration: () => ({ + fakeTraffic: this._config.fakeTraffic.enabled, + decoyChannels: this._config.decoyChannels.enabled, + packetPadding: this._config.packetPadding.enabled, + antiFingerprinting: this._config.antiFingerprinting.enabled + }), + emergency: {} + }; + if (typeof this._emergencyUnlockAllMutexes === "function") { + safeGlobalAPI.emergency.unlockAllMutexes = this._emergencyUnlockAllMutexes.bind(this); + } + if (typeof this._emergencyRecoverMutexSystem === "function") { + safeGlobalAPI.emergency.recoverMutexSystem = this._emergencyRecoverMutexSystem.bind(this); + } + if (typeof this._emergencyDisableLogging === "function") { + safeGlobalAPI.emergency.disableLogging = this._emergencyDisableLogging.bind(this); + } + if (typeof this._resetLoggingSystem === "function") { + safeGlobalAPI.emergency.resetLogging = this._resetLoggingSystem.bind(this); + } + safeGlobalAPI.getFileTransferSystemStatus = () => ({ + initialized: !!this.fileTransferSystem, + status: "ready", + activeTransfers: 0, + receivingTransfers: 0 + }); + this._secureLog("info", "\u{1F512} API methods available", { + sendMessage: !!secureAPI.sendMessage, + getConnectionStatus: !!secureAPI.getConnectionStatus, + getSecurityStatus: !!secureAPI.getSecurityStatus, + sendFile: !!secureAPI.sendFile, + getFileTransferStatus: !!secureAPI.getFileTransferStatus, + disconnect: !!secureAPI.disconnect, + getConfiguration: !!safeGlobalAPI.getConfiguration, + emergencyMethods: Object.keys(safeGlobalAPI.emergency).length + }); + Object.freeze(safeGlobalAPI); + Object.freeze(safeGlobalAPI.emergency); + this._createProtectedGlobalAPI(safeGlobalAPI); + this._setupMinimalGlobalProtection(); + this._secureLog("info", "\u{1F512} Secure global API setup completed successfully"); + } + /** + * Create simple global API export + */ + _createProtectedGlobalAPI(safeGlobalAPI) { + this._secureLog("info", "\u{1F512} Creating protected global API"); + if (!window.secureBitChat) { + this._exportAPI(safeGlobalAPI); + } else { + this._secureLog("warn", "\u26A0\uFE0F Global API already exists, skipping setup"); + } + } + /** + * Simple API export without monitoring + */ + _exportAPI(apiObject) { + this._secureLog("info", "\u{1F512} Exporting API to window.secureBitChat"); + if (!this._importantMethods || !this._importantMethods.defineProperty) { + this._secureLog("error", "\u274C Important methods not available for API export, using fallback"); + Object.defineProperty(window, "secureBitChat", { + value: apiObject, + writable: false, + configurable: false, + enumerable: true + }); + } else { + this._importantMethods.defineProperty(window, "secureBitChat", { + value: apiObject, + writable: false, + configurable: false, + enumerable: true + }); + } + this._secureLog("info", "\u{1F512} Secure API exported to window.secureBitChat"); + } + /** + * Setup minimal global protection + */ + _setupMinimalGlobalProtection() { + this._protectGlobalAPI(); + this._secureLog("info", "\u{1F512} Minimal global protection activated"); + } + /** + * Store important methods in closure for local use + */ + _storeImportantMethods() { + this._importantMethods = { + defineProperty: Object.defineProperty, + getOwnPropertyDescriptor: Object.getOwnPropertyDescriptor, + freeze: Object.freeze, + consoleLog: console.log, + consoleError: console.error, + consoleWarn: console.warn + }; + this._secureLog("info", "\u{1F512} Important methods stored locally", { + defineProperty: !!this._importantMethods.defineProperty, + getOwnPropertyDescriptor: !!this._importantMethods.getOwnPropertyDescriptor, + freeze: !!this._importantMethods.freeze + }); + } + /** + * Simple protection without monitoring + */ + _setupSimpleProtection() { + this._secureLog("info", "\u{1F512} Simple protection activated - no monitoring"); + } + /** + * No global exposure prevention needed + */ + _preventGlobalExposure() { + this._secureLog("info", "\u{1F512} No global exposure prevention - using secure API export only"); + } + /** + * API integrity check - only at initialization + */ + _verifyAPIIntegrity() { + try { + if (!window.secureBitChat) { + this._secureLog("error", "\u274C SECURITY ALERT: Secure API has been removed!"); + return false; + } + const requiredMethods = ["sendMessage", "getConnectionStatus", "disconnect"]; + const missingMethods = requiredMethods.filter( + (method) => typeof window.secureBitChat[method] !== "function" + ); + if (missingMethods.length > 0) { + this._secureLog("error", "\u274C SECURITY ALERT: API tampering detected, missing methods:", { errorType: missingMethods?.constructor?.name || "Unknown" }); + return false; + } + return true; + } catch (error) { + this._secureLog("error", "\u274C SECURITY ALERT: API integrity check failed:", { errorType: error?.constructor?.name || "Unknown" }); + return false; + } + } + // ============================================ + // ADDITIONAL SECURITY METHODS + // ============================================ + /** + * Simple global exposure check - only at initialization + */ + _auditGlobalExposure() { + this._secureLog("info", "\u{1F512} Global exposure check completed at initialization"); + return []; + } + /** + * No periodic security audits - only at initialization + */ + _startSecurityAudit() { + this._secureLog("info", "\u{1F512} Security audit completed at initialization - no periodic monitoring"); + } + /** + * Simple global API protection + */ + _protectGlobalAPI() { + if (!window.secureBitChat) { + this._secureLog("warn", "\u26A0\uFE0F Global API not found during protection setup"); + return; + } + try { + if (this._validateAPIIntegrityOnce()) { + this._secureLog("info", "\u{1F512} Global API protection verified"); + } + } catch (error) { + this._secureLog("error", "\u274C Failed to verify global API protection", { + errorType: error.constructor.name, + errorMessage: error.message + }); + } + } + /** + * Validate API integrity once at initialization + */ + _validateAPIIntegrityOnce() { + try { + if (!this._importantMethods || !this._importantMethods.getOwnPropertyDescriptor) { + const descriptor = Object.getOwnPropertyDescriptor(window, "secureBitChat"); + if (!descriptor || descriptor.configurable) { + throw new Error("secureBitChat must not be reconfigurable!"); + } + } else { + const descriptor = this._importantMethods.getOwnPropertyDescriptor(window, "secureBitChat"); + if (!descriptor || descriptor.configurable) { + throw new Error("secureBitChat must not be reconfigurable!"); + } + } + this._secureLog("info", "\u2705 API integrity validated"); + return true; + } catch (error) { + this._secureLog("error", "\u274C API integrity validation failed", { + errorType: error.constructor.name, + errorMessage: error.message + }); + return false; + } + } + /** + * Secure memory wipe for sensitive data + */ + _secureWipeMemory(data, context = "unknown") { + if (!data) return; + try { + if (data instanceof ArrayBuffer) { + this._secureWipeArrayBuffer(data, context); + } else if (data instanceof Uint8Array) { + this._secureWipeUint8Array(data, context); + } else if (Array.isArray(data)) { + this._secureWipeArray(data, context); + } else if (typeof data === "string") { + this._secureWipeString(data, context); + } else if (data instanceof CryptoKey) { + this._secureWipeCryptoKey(data, context); + } else if (typeof data === "object") { + this._secureWipeObject(data, context); + } + this._secureMemoryManager.memoryStats.totalCleanups++; + } catch (error) { + this._secureMemoryManager.memoryStats.failedCleanups++; + this._secureLog("error", "\u274C Secure memory wipe failed", { + context, + errorType: error.constructor.name, + errorMessage: error.message + }); + } + } + /** + * Secure wipe for ArrayBuffer + */ + _secureWipeArrayBuffer(buffer, context) { + if (!buffer || buffer.byteLength === 0) return; + try { + const view = new Uint8Array(buffer); + crypto.getRandomValues(view); + view.fill(0); + view.fill(255); + view.fill(0); + this._secureLog("debug", "\u{1F512} ArrayBuffer securely wiped", { + context, + size: buffer.byteLength + }); + } catch (error) { + this._secureLog("error", "\u274C Failed to wipe ArrayBuffer", { + context, + errorType: error.constructor.name + }); + } + } + /** + * Secure wipe for Uint8Array + */ + _secureWipeUint8Array(array, context) { + if (!array || array.length === 0) return; + try { + crypto.getRandomValues(array); + array.fill(0); + array.fill(255); + array.fill(0); + this._secureLog("debug", "\u{1F512} Uint8Array securely wiped", { + context, + size: array.length + }); + } catch (error) { + this._secureLog("error", "\u274C Failed to wipe Uint8Array", { + context, + errorType: error.constructor.name + }); + } + } + /** + * Secure wipe for arrays + */ + _secureWipeArray(array, context) { + if (!Array.isArray(array) || array.length === 0) return; + try { + array.forEach((item, index) => { + if (item !== null && item !== void 0) { + this._secureWipeMemory(item, `${context}[${index}]`); + } + }); + array.fill(null); + this._secureLog("debug", "\u{1F512} Array securely wiped", { + context, + size: array.length + }); + } catch (error) { + this._secureLog("error", "\u274C Failed to wipe array", { + context, + errorType: error.constructor.name + }); + } + } + /** + * No string wiping - strings are immutable in JS + */ + _secureWipeString(str, context) { + this._secureLog("debug", "\u{1F512} String reference removed (strings are immutable)", { + context, + length: str ? str.length : 0 + }); + } + /** + * CryptoKey cleanup - store in WeakMap for proper GC + */ + _secureWipeCryptoKey(key, context) { + if (!key || !(key instanceof CryptoKey)) return; + try { + if (!this._cryptoKeyStorage) { + this._cryptoKeyStorage = /* @__PURE__ */ new WeakMap(); + } + this._cryptoKeyStorage.set(key, { + context, + timestamp: Date.now(), + type: key.type + }); + this._secureLog("debug", "\u{1F512} CryptoKey stored in WeakMap for cleanup", { + context, + type: key.type + }); + } catch (error) { + this._secureLog("error", "\u274C Failed to store CryptoKey for cleanup", { + context, + errorType: error.constructor.name + }); + } + } + /** + * Secure wipe for objects + */ + _secureWipeObject(obj, context) { + if (!obj || typeof obj !== "object") return; + try { + for (const [key, value] of Object.entries(obj)) { + if (value !== null && value !== void 0) { + this._secureWipeMemory(value, `${context}.${key}`); + } + obj[key] = null; + } + this._secureLog("debug", "\u{1F512} Object securely wiped", { + context, + properties: Object.keys(obj).length + }); + } catch (error) { + this._secureLog("error", "\u274C Failed to wipe object", { + context, + errorType: error.constructor.name + }); + } + } + /** + * Secure cleanup of cryptographic materials + */ + _secureCleanupCryptographicMaterials() { + try { + if (this.ecdhKeyPair) { + this._secureWipeMemory(this.ecdhKeyPair, "ecdhKeyPair"); + this.ecdhKeyPair = null; + } + if (this.ecdsaKeyPair) { + this._secureWipeMemory(this.ecdsaKeyPair, "ecdsaKeyPair"); + this.ecdsaKeyPair = null; + } + if (this.encryptionKey) { + this._secureWipeMemory(this.encryptionKey, "encryptionKey"); + this.encryptionKey = null; + } + if (this.macKey) { + this._secureWipeMemory(this.macKey, "macKey"); + this.macKey = null; + } + if (this.metadataKey) { + this._secureWipeMemory(this.metadataKey, "metadataKey"); + this.metadataKey = null; + } + if (this.nestedEncryptionKey) { + this._secureWipeMemory(this.nestedEncryptionKey, "nestedEncryptionKey"); + this.nestedEncryptionKey = null; + } + if (this.sessionSalt) { + this._secureWipeMemory(this.sessionSalt, "sessionSalt"); + this.sessionSalt = null; + } + if (this.sessionId) { + this._secureWipeMemory(this.sessionId, "sessionId"); + this.sessionId = null; + } + if (this.verificationCode) { + this._secureWipeMemory(this.verificationCode, "verificationCode"); + this.verificationCode = null; + } + if (this.peerPublicKey) { + this._secureWipeMemory(this.peerPublicKey, "peerPublicKey"); + this.peerPublicKey = null; + } + if (this.keyFingerprint) { + this._secureWipeMemory(this.keyFingerprint, "keyFingerprint"); + this.keyFingerprint = null; + } + if (this.connectionId) { + this._secureWipeMemory(this.connectionId, "connectionId"); + this.connectionId = null; + } + this._secureLog("info", "\u{1F512} Cryptographic materials securely cleaned up"); + } catch (error) { + this._secureLog("error", "\u274C Failed to cleanup cryptographic materials", { + errorType: error.constructor.name, + errorMessage: error.message + }); + } + } + /** + * Force garbage collection if available + */ + _forceGarbageCollection() { + try { + if (typeof window.gc === "function") { + window.gc(); + this._secureLog("debug", "\u{1F512} Garbage collection forced"); + } else if (typeof global.gc === "function") { + global.gc(); + this._secureLog("debug", "\u{1F512} Garbage collection forced (global)"); + } else { + this._secureLog("debug", "\u26A0\uFE0F Garbage collection not available"); + } + } catch (error) { + this._secureLog("error", "\u274C Failed to force garbage collection", { + errorType: error.constructor.name + }); + } + } + /** + * Perform periodic memory cleanup + */ + _performPeriodicMemoryCleanup() { + try { + this._secureMemoryManager.isCleaning = true; + this._secureCleanupCryptographicMaterials(); + if (this.messageQueue && this.messageQueue.length > 100) { + const excessMessages = this.messageQueue.splice(0, this.messageQueue.length - 50); + excessMessages.forEach((message, index) => { + this._secureWipeMemory(message, `periodicCleanup[${index}]`); + }); + } + if (this.processedMessageIds && this.processedMessageIds.size > 1e3) { + this.processedMessageIds.clear(); + } + this._forceGarbageCollection(); + this._secureLog("debug", "\u{1F512} Periodic memory cleanup completed"); + } catch (error) { + this._secureLog("error", "\u274C Error during periodic memory cleanup", { + errorType: error.constructor.name, + errorMessage: error.message + }); + } finally { + this._secureMemoryManager.isCleaning = false; + } + } + /** + * Create secure error message without information disclosure + */ + _createSecureErrorMessage(originalError, context = "unknown") { + try { + const category = this._categorizeError(originalError); + const safeMessage = this._getSafeErrorMessage(category, context); + this._secureLog("error", "Internal error occurred", { + category, + context, + errorType: originalError?.constructor?.name || "Unknown", + timestamp: Date.now() + }); + this._trackErrorFrequency(category); + return safeMessage; + } catch (error) { + this._secureLog("error", "Error handling failed", { + originalError: originalError?.message || "Unknown", + handlingError: error.message + }); + return "An unexpected error occurred"; + } + } + /** + * Categorize error for appropriate handling + */ + _categorizeError(error) { + if (!error || !error.message) { + return this._secureErrorHandler.errorCategories.UNKNOWN; + } + const message = error.message.toLowerCase(); + if (message.includes("crypto") || message.includes("key") || message.includes("encrypt") || message.includes("decrypt") || message.includes("sign") || message.includes("verify") || message.includes("ecdh") || message.includes("ecdsa")) { + return this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC; + } + if (message.includes("network") || message.includes("connection") || message.includes("timeout") || message.includes("webrtc") || message.includes("peer")) { + return this._secureErrorHandler.errorCategories.NETWORK; + } + if (message.includes("invalid") || message.includes("validation") || message.includes("format") || message.includes("type")) { + return this._secureErrorHandler.errorCategories.VALIDATION; + } + if (message.includes("system") || message.includes("internal") || message.includes("memory") || message.includes("resource")) { + return this._secureErrorHandler.errorCategories.SYSTEM; + } + return this._secureErrorHandler.errorCategories.UNKNOWN; + } + /** + * Get safe error message based on category + */ + _getSafeErrorMessage(category, context) { + const safeMessages = { + [this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC]: { + "key_generation": "Security initialization failed", + "key_import": "Security verification failed", + "key_derivation": "Security setup failed", + "encryption": "Message security failed", + "decryption": "Message verification failed", + "signature": "Authentication failed", + "default": "Security operation failed" + }, + [this._secureErrorHandler.errorCategories.NETWORK]: { + "connection": "Connection failed", + "timeout": "Connection timeout", + "peer": "Peer connection failed", + "webrtc": "Communication failed", + "default": "Network operation failed" + }, + [this._secureErrorHandler.errorCategories.VALIDATION]: { + "format": "Invalid data format", + "type": "Invalid data type", + "structure": "Invalid data structure", + "default": "Validation failed" + }, + [this._secureErrorHandler.errorCategories.SYSTEM]: { + "memory": "System resource error", + "resource": "System resource unavailable", + "internal": "Internal system error", + "default": "System operation failed" + }, + [this._secureErrorHandler.errorCategories.UNKNOWN]: { + "default": "An unexpected error occurred" + } + }; + const categoryMessages = safeMessages[category] || safeMessages[this._secureErrorHandler.errorCategories.UNKNOWN]; + let specificContext = "default"; + if (context.includes("key") || context.includes("crypto")) { + specificContext = category === this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC ? "key_generation" : "default"; + } else if (context.includes("connection") || context.includes("peer")) { + specificContext = category === this._secureErrorHandler.errorCategories.NETWORK ? "connection" : "default"; + } else if (context.includes("validation") || context.includes("format")) { + specificContext = category === this._secureErrorHandler.errorCategories.VALIDATION ? "format" : "default"; + } + return categoryMessages[specificContext] || categoryMessages.default; + } + /** + * Track error frequency for security monitoring + */ + _trackErrorFrequency(category) { + const now = Date.now(); + if (now - this._secureErrorHandler.lastErrorTime > 6e4) { + this._secureErrorHandler.errorCounts.clear(); + } + const currentCount = this._secureErrorHandler.errorCounts.get(category) || 0; + this._secureErrorHandler.errorCounts.set(category, currentCount + 1); + this._secureErrorHandler.lastErrorTime = now; + const totalErrors = Array.from(this._secureErrorHandler.errorCounts.values()).reduce((sum, count) => sum + count, 0); + if (totalErrors > this._secureErrorHandler.errorThreshold) { + this._secureErrorHandler.isInErrorMode = true; + this._secureLog("warn", "\u26A0\uFE0F High error frequency detected - entering error mode", { + totalErrors, + threshold: this._secureErrorHandler.errorThreshold + }); + } + } + /** + * Throw secure error without information disclosure + */ + _throwSecureError(originalError, context = "unknown") { + const secureMessage = this._createSecureErrorMessage(originalError, context); + throw new Error(secureMessage); + } + /** + * Get error handling statistics + */ + _getErrorHandlingStats() { + return { + errorCounts: Object.fromEntries(this._secureErrorHandler.errorCounts), + isInErrorMode: this._secureErrorHandler.isInErrorMode, + lastErrorTime: this._secureErrorHandler.lastErrorTime, + errorThreshold: this._secureErrorHandler.errorThreshold + }; + } + /** + * Reset error handling system + */ + _resetErrorHandlingSystem() { + this._secureErrorHandler.errorCounts.clear(); + this._secureErrorHandler.isInErrorMode = false; + this._secureErrorHandler.lastErrorTime = 0; + this._secureLog("info", "\u{1F504} Error handling system reset"); + } + /** + * Get memory management statistics + */ + _getMemoryManagementStats() { + return { + totalCleanups: this._secureMemoryManager.memoryStats.totalCleanups, + failedCleanups: this._secureMemoryManager.memoryStats.failedCleanups, + lastCleanup: this._secureMemoryManager.memoryStats.lastCleanup, + isCleaning: this._secureMemoryManager.isCleaning, + queueLength: this._secureMemoryManager.cleanupQueue.length + }; + } + /** + * Validate API integrity and security + */ + _validateAPIIntegrity() { + try { + if (!window.secureBitChat) { + this._secureLog("error", "\u274C Global API not found during integrity validation"); + return false; + } + const requiredMethods = ["sendMessage", "getConnectionStatus", "getSecurityStatus", "sendFile", "disconnect"]; + const missingMethods = requiredMethods.filter( + (method) => !window.secureBitChat[method] || typeof window.secureBitChat[method] !== "function" + ); + if (missingMethods.length > 0) { + this._secureLog("error", "\u274C Global API integrity validation failed - missing methods", { + missingMethods + }); + return false; + } + const testContext = { test: true }; + const boundMethods = requiredMethods.map((method) => { + try { + return window.secureBitChat[method].bind(testContext); + } catch (error) { + return null; + } + }); + const unboundMethods = boundMethods.filter((method) => method === null); + if (unboundMethods.length > 0) { + this._secureLog("error", "\u274C Global API integrity validation failed - method binding issues", { + unboundMethods: unboundMethods.length + }); + return false; + } + try { + const testProp = "_integrity_test_" + Date.now(); + Object.defineProperty(window.secureBitChat, testProp, { + value: "test", + writable: true, + configurable: true + }); + this._secureLog("error", "\u274C Global API integrity validation failed - API is mutable"); + delete window.secureBitChat[testProp]; + return false; + } catch (immutabilityError) { + this._secureLog("debug", "\u2705 Global API immutability verified"); + } + this._secureLog("info", "\u2705 Global API integrity validation passed"); + return true; + } catch (error) { + this._secureLog("error", "\u274C Global API integrity validation failed", { + errorType: error.constructor.name, + errorMessage: error.message + }); + return false; + } + } + _validateCryptographicSecurity() { + const criticalFeatures = ["hasRateLimiting"]; + const missingCritical = criticalFeatures.filter((feature) => !this.securityFeatures[feature]); + if (missingCritical.length > 0) { + this._secureLog("error", "\u{1F6A8} CRITICAL: Missing critical rate limiting feature", { + missing: missingCritical, + currentFeatures: this.securityFeatures, + action: "Rate limiting will be forced enabled" + }); + missingCritical.forEach((feature) => { + this.securityFeatures[feature] = true; + this._secureLog("warn", `\u26A0\uFE0F Forced enable critical: ${feature} = true`); + }); + } + const availableFeatures = Object.keys(this.securityFeatures).filter((f) => this.securityFeatures[f]); + const encryptionFeatures = ["hasEncryption", "hasECDH", "hasECDSA"].filter((f) => this.securityFeatures[f]); + this._secureLog("info", "\u2705 Cryptographic security validation passed", { + criticalFeatures: criticalFeatures.length, + availableFeatures: availableFeatures.length, + encryptionFeatures: encryptionFeatures.length, + totalSecurityFeatures: availableFeatures.length, + note: "Encryption features will be enabled after key generation", + currentState: { + hasEncryption: this.securityFeatures.hasEncryption, + hasECDH: this.securityFeatures.hasECDH, + hasECDSA: this.securityFeatures.hasECDSA, + hasRateLimiting: this.securityFeatures.hasRateLimiting + } + }); + return true; + } + _syncSecurityFeaturesWithTariff() { + if (!this.sessionManager || !this.sessionManager.isFeatureAllowedForSession) { + this._secureLog("warn", "\u26A0\uFE0F Session manager not available, using safe default security features"); + if (this.securityFeatures.hasEncryption === void 0) { + this.securityFeatures.hasEncryption = false; + } + if (this.securityFeatures.hasECDH === void 0) { + this.securityFeatures.hasECDH = false; + } + if (this.securityFeatures.hasECDSA === void 0) { + this.securityFeatures.hasECDSA = false; + } + if (this.securityFeatures.hasMutualAuth === void 0) { + this.securityFeatures.hasMutualAuth = false; + } + if (this.securityFeatures.hasMetadataProtection === void 0) { + this.securityFeatures.hasMetadataProtection = false; + } + if (this.securityFeatures.hasEnhancedReplayProtection === void 0) { + this.securityFeatures.hasEnhancedReplayProtection = false; + } + if (this.securityFeatures.hasNonExtractableKeys === void 0) { + this.securityFeatures.hasNonExtractableKeys = false; + } + if (this.securityFeatures.hasRateLimiting === void 0) { + this.securityFeatures.hasRateLimiting = true; + } + if (this.securityFeatures.hasEnhancedValidation === void 0) { + this.securityFeatures.hasEnhancedValidation = false; + } + if (this.securityFeatures.hasPFS === void 0) { + this.securityFeatures.hasPFS = false; + } + if (this.securityFeatures.hasNestedEncryption === void 0) { + this.securityFeatures.hasNestedEncryption = false; + } + if (this.securityFeatures.hasPacketPadding === void 0) { + this.securityFeatures.hasPacketPadding = false; + } + if (this.securityFeatures.hasPacketReordering === void 0) { + this.securityFeatures.hasPacketReordering = false; + } + if (this.securityFeatures.hasAntiFingerprinting === void 0) { + this.securityFeatures.hasAntiFingerprinting = false; + } + if (this.securityFeatures.hasFakeTraffic === void 0) { + this.securityFeatures.hasFakeTraffic = false; + } + if (this.securityFeatures.hasDecoyChannels === void 0) { + this.securityFeatures.hasDecoyChannels = false; + } + if (this.securityFeatures.hasMessageChunking === void 0) { + this.securityFeatures.hasMessageChunking = false; + } + this._secureLog("info", "\u2705 Safe default security features applied (features will be enabled as they become available)"); + return; + } + let sessionType = "demo"; + if (this.sessionManager.isFeatureAllowedForSession("premium", "hasFakeTraffic")) { + sessionType = "premium"; + } else if (this.sessionManager.isFeatureAllowedForSession("basic", "hasECDSA")) { + sessionType = "basic"; + } + this._secureLog("info", "\u{1F512} Syncing security features with tariff plan", { sessionType }); + const allFeatures = [ + "hasEncryption", + "hasECDH", + "hasECDSA", + "hasMutualAuth", + "hasMetadataProtection", + "hasEnhancedReplayProtection", + "hasNonExtractableKeys", + "hasRateLimiting", + "hasEnhancedValidation", + "hasPFS", + "hasNestedEncryption", + "hasPacketPadding", + "hasPacketReordering", + "hasAntiFingerprinting", + "hasFakeTraffic", + "hasDecoyChannels", + "hasMessageChunking" + ]; + allFeatures.forEach((feature) => { + const isAllowed = this.sessionManager.isFeatureAllowedForSession(sessionType, feature); + if (this.securityFeatures[feature] !== isAllowed) { + this._secureLog("info", `\u{1F504} Syncing ${feature}: ${this.securityFeatures[feature]} \u2192 ${isAllowed}`); + this.securityFeatures[feature] = isAllowed; + } + }); + if (this.onStatusChange) { + this.onStatusChange("security_synced", { + type: "tariff_sync", + sessionType, + features: this.securityFeatures, + message: `Security features synchronized with ${sessionType} tariff plan` + }); + } + this._secureLog("info", "\u2705 Security features synchronized with tariff plan", { + sessionType, + enabledFeatures: Object.keys(this.securityFeatures).filter((f) => this.securityFeatures[f]).length, + totalFeatures: Object.keys(this.securityFeatures).length + }); + } + /** + * Emergency shutdown for critical issues + */ + _emergencyShutdown(reason = "Security breach") { + this._secureLog("error", "\u274C EMERGENCY SHUTDOWN: ${reason}"); + try { + this.encryptionKey = null; + this.macKey = null; + this.metadataKey = null; + this.verificationCode = null; + this.keyFingerprint = null; + this.connectionId = null; + if (this.dataChannel) { + this.dataChannel.close(); + this.dataChannel = null; + } + if (this.peerConnection) { + this.peerConnection.close(); + this.peerConnection = null; + } + this.messageQueue = []; + this.processedMessageIds.clear(); + this.packetBuffer.clear(); + if (this.onStatusChange) { + this.onStatusChange("security_breach"); + } + this._secureLog("info", "\u{1F512} Emergency shutdown completed"); + } catch (error) { + this._secureLog("error", "\u274C Error during emergency shutdown:", { errorType: error?.constructor?.name || "Unknown" }); + } + } + _finalizeSecureInitialization() { + this._startKeySecurityMonitoring(); + if (!this._verifyAPIIntegrity()) { + this._secureLog("error", "\u274C Security initialization failed"); + return; + } + this._startSecurityMonitoring(); + setInterval(() => { + this._cleanupLogs(); + }, 3e5); + this._secureLog("info", "\u2705 Secure WebRTC Manager initialization completed"); + this._secureLog("info", "\u{1F512} Global exposure protection: Monitoring only, no automatic removal"); + } + /** + * Start security monitoring + * @deprecated Use unified scheduler instead + */ + _startSecurityMonitoring() { + this._secureLog("info", "\u{1F527} Security monitoring moved to unified scheduler"); + } + /** + * Validates connection readiness for sending data + * @param {boolean} throwError - whether to throw on not ready + * @returns {boolean} true if connection is ready + */ + _validateConnection(throwError = true) { + const isDataChannelReady = this.dataChannel && this.dataChannel.readyState === "open"; + const isConnectionVerified = this.isVerified; + const isValid = isDataChannelReady && isConnectionVerified; + if (!isValid && throwError) { + if (!isDataChannelReady) { + throw new Error("Data channel not ready"); + } + if (!isConnectionVerified) { + throw new Error("Connection not verified"); + } + } + return isValid; + } + /** + * Hard gate for traffic blocking without verification + * This method enforces that NO traffic (including system messages and file transfers) + * can pass through without proper cryptographic verification + */ + _enforceVerificationGate(operation = "unknown", throwError = true) { + if (!this.isVerified) { + const errorMessage = `SECURITY VIOLATION: ${operation} blocked - connection not cryptographically verified`; + this._secureLog("error", errorMessage, { + operation, + isVerified: this.isVerified, + hasKeys: !!(this.encryptionKey && this.macKey), + timestamp: Date.now() + }); + if (throwError) { + throw new Error(errorMessage); + } + return false; + } + return true; + } + /** + * Safe method to set isVerified only after cryptographic verification + * This is the ONLY method that should set isVerified = true + */ + _setVerifiedStatus(verified, verificationMethod = "unknown", verificationData = null) { + if (verified) { + if (!this.encryptionKey || !this.macKey) { + throw new Error("Cannot set verified=true without encryption keys"); + } + if (!verificationMethod || verificationMethod === "unknown") { + throw new Error("Cannot set verified=true without specifying verification method"); + } + this._secureLog("info", "Connection verified through cryptographic verification", { + verificationMethod, + hasEncryptionKey: !!this.encryptionKey, + hasMacKey: !!this.macKey, + keyFingerprint: this.keyFingerprint, + timestamp: Date.now(), + verificationData: verificationData ? "provided" : "none" + }); + } + this.isVerified = verified; + if (verified) { + this.onStatusChange("connected"); + } else { + this.onStatusChange("disconnected"); + } + } + /** + * Create AAD (Additional Authenticated Data) for file messages + * This binds file messages to the current session and prevents replay attacks + */ + _createFileMessageAAD(messageType, messageData = null) { + if (typeof this._createMessageAAD !== "function") { + throw new Error("_createMessageAAD method is not available in _createFileMessageAAD. Manager may not be fully initialized."); + } + return this._createMessageAAD(messageType, messageData, true); + } + /** + * Validate AAD for file messages + * This ensures file messages are bound to the correct session + */ + _validateFileMessageAAD(aadString, expectedMessageType = null) { + try { + const aad = JSON.parse(aadString); + if (aad.sessionId !== (this.currentSession?.sessionId || "unknown")) { + throw new Error("AAD sessionId mismatch - possible replay attack"); + } + if (aad.keyFingerprint !== (this.keyFingerprint || "unknown")) { + throw new Error("AAD keyFingerprint mismatch - possible key substitution attack"); + } + if (expectedMessageType && aad.messageType !== expectedMessageType) { + throw new Error(`AAD messageType mismatch - expected ${expectedMessageType}, got ${aad.messageType}`); + } + const now = Date.now(); + const messageAge = now - aad.timestamp; + if (messageAge > 3e5) { + throw new Error("AAD timestamp too old - possible replay attack"); + } + return aad; + } catch (error) { + this._secureLog("error", "AAD validation failed", { error: error.message, aadString }); + throw new Error(`AAD validation failed: ${error.message}`); + } + } + /** + * Extract DTLS fingerprint from SDP + * This is essential for MITM protection + */ + _extractDTLSFingerprintFromSDP(sdp) { + try { + if (!sdp || typeof sdp !== "string") { + throw new Error("Invalid SDP provided"); + } + const fingerprintRegex = /a=fingerprint:([a-zA-Z0-9-]+)\s+([A-Fa-f0-9:]+)/g; + const fingerprints = []; + let match; + while ((match = fingerprintRegex.exec(sdp)) !== null) { + fingerprints.push({ + algorithm: match[1].toLowerCase(), + fingerprint: match[2].toLowerCase().replace(/:/g, "") + }); + } + if (fingerprints.length === 0) { + const altFingerprintRegex = /fingerprint\s*=\s*([a-zA-Z0-9-]+)\s+([A-Fa-f0-9:]+)/gi; + while ((match = altFingerprintRegex.exec(sdp)) !== null) { + fingerprints.push({ + algorithm: match[1].toLowerCase(), + fingerprint: match[2].toLowerCase().replace(/:/g, "") + }); + } + } + if (fingerprints.length === 0) { + this._secureLog("warn", "No DTLS fingerprints found in SDP - this may be normal for some WebRTC implementations", { + sdpLength: sdp.length, + sdpPreview: sdp.substring(0, 200) + "..." + }); + throw new Error("No DTLS fingerprints found in SDP"); + } + const sha256Fingerprint = fingerprints.find((fp) => fp.algorithm === "sha-256"); + if (sha256Fingerprint) { + return sha256Fingerprint.fingerprint; + } + return fingerprints[0].fingerprint; + } catch (error) { + this._secureLog("error", "Failed to extract DTLS fingerprint from SDP", { + error: error.message, + sdpLength: sdp?.length || 0 + }); + throw new Error(`DTLS fingerprint extraction failed: ${error.message}`); + } + } + /** + * Validate DTLS fingerprint against expected value + * This prevents MITM attacks by ensuring the remote peer has the expected certificate + */ + _validateDTLSFingerprint(receivedFingerprint, expectedFingerprint, context = "unknown") { + try { + if (!receivedFingerprint || !expectedFingerprint) { + throw new Error("Missing fingerprint for validation"); + } + const normalizedReceived = receivedFingerprint.toLowerCase().replace(/:/g, ""); + const normalizedExpected = expectedFingerprint.toLowerCase().replace(/:/g, ""); + if (normalizedReceived !== normalizedExpected) { + this._secureLog("error", "DTLS fingerprint mismatch - possible MITM attack", { + context, + received: normalizedReceived, + expected: normalizedExpected, + timestamp: Date.now() + }); + throw new Error(`DTLS fingerprint mismatch - possible MITM attack in ${context}`); + } + this._secureLog("info", "DTLS fingerprint validation successful", { + context, + fingerprint: normalizedReceived, + timestamp: Date.now() + }); + return true; + } catch (error) { + this._secureLog("error", "DTLS fingerprint validation failed", { + error: error.message, + context + }); + throw error; + } + } + /** + * Compute SAS (Short Authentication String) for MITM protection + * Uses HKDF with DTLS fingerprints to generate a stable 7-digit verification code + * @param {ArrayBuffer|Uint8Array} keyMaterialRaw - Shared secret or key fingerprint data + * @param {string} localFP - Local DTLS fingerprint + * @param {string} remoteFP - Remote DTLS fingerprint + * @returns {Promise} 7-digit SAS code + */ + async _computeSAS(keyMaterialRaw, localFP, remoteFP) { + try { + console.log("_computeSAS called with parameters:", { + keyMaterialRaw: keyMaterialRaw ? `${keyMaterialRaw.constructor.name} (${keyMaterialRaw.length || keyMaterialRaw.byteLength} bytes)` : "null/undefined", + localFP: localFP ? `${localFP.substring(0, 20)}...` : "null/undefined", + remoteFP: remoteFP ? `${remoteFP.substring(0, 20)}...` : "null/undefined" + }); + if (!keyMaterialRaw || !localFP || !remoteFP) { + const missing = []; + if (!keyMaterialRaw) missing.push("keyMaterialRaw"); + if (!localFP) missing.push("localFP"); + if (!remoteFP) missing.push("remoteFP"); + throw new Error(`Missing required parameters for SAS computation: ${missing.join(", ")}`); + } + const enc = new TextEncoder(); + const salt = enc.encode( + "webrtc-sas|" + [localFP, remoteFP].sort().join("|") + ); + let keyBuffer; + if (keyMaterialRaw instanceof ArrayBuffer) { + keyBuffer = keyMaterialRaw; + } else if (keyMaterialRaw instanceof Uint8Array) { + keyBuffer = keyMaterialRaw.buffer; + } else if (typeof keyMaterialRaw === "string") { + const hexString = keyMaterialRaw.replace(/:/g, "").replace(/\s/g, ""); + const bytes = new Uint8Array(hexString.length / 2); + for (let i = 0; i < hexString.length; i += 2) { + bytes[i / 2] = parseInt(hexString.substr(i, 2), 16); + } + keyBuffer = bytes.buffer; + } else { + throw new Error("Invalid keyMaterialRaw type"); + } + const key = await crypto.subtle.importKey( + "raw", + keyBuffer, + "HKDF", + false, + ["deriveBits"] + ); + const info = enc.encode("p2p-sas-v1"); + const bits = await crypto.subtle.deriveBits( + { name: "HKDF", hash: "SHA-256", salt, info }, + key, + 64 + // 64 бита достаточно для 6–7 знаков + ); + const dv = new DataView(bits); + const n = (dv.getUint32(0) ^ dv.getUint32(4)) >>> 0; + const sasCode = String(n % 1e7).padStart(7, "0"); + console.log("\u{1F3AF} _computeSAS computed code:", sasCode, "(type:", typeof sasCode, ")"); + this._secureLog("info", "SAS code computed successfully", { + localFP: localFP.substring(0, 16) + "...", + remoteFP: remoteFP.substring(0, 16) + "...", + sasLength: sasCode.length, + timestamp: Date.now() + }); + return sasCode; + } catch (error) { + this._secureLog("error", "SAS computation failed", { + error: error.message, + keyMaterialType: typeof keyMaterialRaw, + hasLocalFP: !!localFP, + hasRemoteFP: !!remoteFP, + timestamp: Date.now() + }); + throw new Error(`SAS computation failed: ${error.message}`); + } + } + /** + * UTILITY: Decode hex keyFingerprint to Uint8Array for SAS computation + * @param {string} hexString - Hex encoded keyFingerprint (e.g., "aa:bb:cc:dd") + * @returns {Uint8Array} Decoded bytes + */ + _decodeKeyFingerprint(hexString) { + try { + if (!hexString || typeof hexString !== "string") { + throw new Error("Invalid hex string provided"); + } + return window.EnhancedSecureCryptoUtils.hexToUint8Array(hexString); + } catch (error) { + this._secureLog("error", "Key fingerprint decoding failed", { + error: error.message, + inputType: typeof hexString, + inputLength: hexString?.length || 0 + }); + throw new Error(`Key fingerprint decoding failed: ${error.message}`); + } + } + /** + * Emergency key wipe on fingerprint mismatch + * This ensures no sensitive data remains if MITM is detected + */ + _emergencyWipeOnFingerprintMismatch(reason = "DTLS fingerprint mismatch") { + try { + this._secureLog("error", "\u{1F6A8} EMERGENCY: Initiating security wipe due to fingerprint mismatch", { + reason, + timestamp: Date.now() + }); + this._secureWipeKeys(); + this._secureWipeMemory(this.encryptionKey, "emergency_wipe"); + this._secureWipeMemory(this.macKey, "emergency_wipe"); + this._secureWipeMemory(this.metadataKey, "emergency_wipe"); + this._wipeEphemeralKeys(); + this._hardWipeOldKeys(); + this.isVerified = null; + this.verificationCode = null; + this.keyFingerprint = null; + this.connectionId = null; + this.expectedDTLSFingerprint = null; + this.disconnect(); + this.deliverMessageToUI("\u{1F6A8} SECURITY BREACH: Connection terminated due to fingerprint mismatch. Possible MITM attack detected!", "system"); + } catch (error) { + this._secureLog("error", "Failed to perform emergency wipe", { error: error.message }); + } + } + /** + * Set expected DTLS fingerprint via out-of-band channel + * This should be called after receiving the fingerprint through a secure channel + * (e.g., QR code, voice call, in-person exchange, etc.) + */ + setExpectedDTLSFingerprint(fingerprint, source = "out_of_band") { + try { + if (!fingerprint || typeof fingerprint !== "string") { + throw new Error("Invalid fingerprint provided"); + } + const normalizedFingerprint = fingerprint.toLowerCase().replace(/:/g, ""); + if (!/^[a-f0-9]{40,64}$/.test(normalizedFingerprint)) { + throw new Error("Invalid fingerprint format - must be hex string"); + } + this.expectedDTLSFingerprint = normalizedFingerprint; + this._secureLog("info", "Expected DTLS fingerprint set via out-of-band channel", { + source, + fingerprint: normalizedFingerprint, + timestamp: Date.now() + }); + this.deliverMessageToUI(`\u2705 DTLS fingerprint set via ${source}. MITM protection enabled.`, "system"); + } catch (error) { + this._secureLog("error", "Failed to set expected DTLS fingerprint", { error: error.message }); + throw error; + } + } + /** + * Get current DTLS fingerprint for out-of-band verification + * This should be shared through a secure channel (QR code, voice, etc.) + */ + getCurrentDTLSFingerprint() { + try { + if (!this.expectedDTLSFingerprint) { + throw new Error("No DTLS fingerprint available - connection not established"); + } + return this.expectedDTLSFingerprint; + } catch (error) { + this._secureLog("error", "Failed to get current DTLS fingerprint", { error: error.message }); + throw error; + } + } + /** + * DEBUGGING: Temporarily disable strict DTLS validation + * This should only be used for debugging connection issues + */ + disableStrictDTLSValidation() { + this.strictDTLSValidation = false; + this._secureLog("warn", "\u26A0\uFE0F Strict DTLS validation disabled - security reduced", { + timestamp: Date.now() + }); + this.deliverMessageToUI("\u26A0\uFE0F DTLS validation disabled for debugging", "system"); + } + /** + * SECURITY: Re-enable strict DTLS validation + */ + enableStrictDTLSValidation() { + this.strictDTLSValidation = true; + this._secureLog("info", "\u2705 Strict DTLS validation re-enabled", { + timestamp: Date.now() + }); + this.deliverMessageToUI("\u2705 DTLS validation re-enabled", "system"); + } + /** + * Generate ephemeral ECDH keys for Perfect Forward Secrecy + * This ensures each session has unique, non-persistent keys + */ + async _generateEphemeralECDHKeys() { + try { + this._secureLog("info", "\u{1F511} Generating ephemeral ECDH keys for PFS", { + sessionStartTime: this.sessionStartTime, + timestamp: Date.now() + }); + const ephemeralKeyPair = await window.EnhancedSecureCryptoUtils.generateECDHKeyPair(); + if (!ephemeralKeyPair || !this._validateKeyPairConstantTime(ephemeralKeyPair)) { + throw new Error("Ephemeral ECDH key pair validation failed"); + } + const sessionId = this.currentSession?.sessionId || `session_${Date.now()}`; + this.ephemeralKeyPairs.set(sessionId, { + keyPair: ephemeralKeyPair, + timestamp: Date.now(), + sessionId + }); + this._secureLog("info", "\u2705 Ephemeral ECDH keys generated for PFS", { + sessionId, + timestamp: Date.now() + }); + return ephemeralKeyPair; + } catch (error) { + this._secureLog("error", "\u274C Failed to generate ephemeral ECDH keys", { error: error.message }); + throw new Error(`Ephemeral key generation failed: ${error.message}`); + } + } + /** + * Hard wipe old keys for real PFS + * This prevents retrospective decryption attacks + */ + _hardWipeOldKeys() { + try { + this._secureLog("info", "\u{1F9F9} Performing hard wipe of old keys for PFS", { + oldKeysCount: this.oldKeys.size, + timestamp: Date.now() + }); + for (const [version, keySet] of this.oldKeys.entries()) { + if (keySet.encryptionKey) { + this._secureWipeMemory(keySet.encryptionKey, "pfs_key_wipe"); + } + if (keySet.macKey) { + this._secureWipeMemory(keySet.macKey, "pfs_key_wipe"); + } + if (keySet.metadataKey) { + this._secureWipeMemory(keySet.metadataKey, "pfs_key_wipe"); + } + keySet.encryptionKey = null; + keySet.macKey = null; + keySet.metadataKey = null; + keySet.keyFingerprint = null; + } + this.oldKeys.clear(); + if (typeof window.gc === "function") { + window.gc(); + } + this._secureLog("info", "\u2705 Hard wipe of old keys completed for PFS", { + timestamp: Date.now() + }); + } catch (error) { + this._secureLog("error", "\u274C Failed to perform hard wipe of old keys", { error: error.message }); + } + } + /** + * Wipe ephemeral keys when session ends + * This ensures session-specific keys are destroyed + */ + _wipeEphemeralKeys() { + try { + this._secureLog("info", "\u{1F9F9} Wiping ephemeral keys for PFS", { + ephemeralKeysCount: this.ephemeralKeyPairs.size, + timestamp: Date.now() + }); + for (const [sessionId, keyData] of this.ephemeralKeyPairs.entries()) { + if (keyData.keyPair?.privateKey) { + this._secureWipeMemory(keyData.keyPair.privateKey, "ephemeral_key_wipe"); + } + if (keyData.keyPair?.publicKey) { + this._secureWipeMemory(keyData.keyPair.publicKey, "ephemeral_key_wipe"); + } + keyData.keyPair = null; + keyData.timestamp = null; + keyData.sessionId = null; + } + this.ephemeralKeyPairs.clear(); + if (typeof window.gc === "function") { + window.gc(); + } + this._secureLog("info", "\u2705 Ephemeral keys wiped for PFS", { + timestamp: Date.now() + }); + } catch (error) { + this._secureLog("error", "\u274C Failed to wipe ephemeral keys", { error: error.message }); + } + } + /** + * Encrypt file messages with AAD + * This ensures file messages are properly authenticated and bound to session + */ + async _encryptFileMessage(messageData, aad) { + try { + if (!this.encryptionKey) { + throw new Error("No encryption key available for file message"); + } + const messageString = typeof messageData === "string" ? messageData : JSON.stringify(messageData); + const encryptedData = await window.EnhancedSecureCryptoUtils.encryptDataWithAAD( + messageString, + this.encryptionKey, + aad + ); + const encryptedMessage = { + type: "encrypted_file_message", + encryptedData, + aad, + timestamp: Date.now(), + keyFingerprint: this.keyFingerprint + }; + return JSON.stringify(encryptedMessage); + } catch (error) { + this._secureLog("error", "Failed to encrypt file message", { error: error.message }); + throw new Error(`File message encryption failed: ${error.message}`); + } + } + /** + * Decrypt file messages with AAD validation + * This ensures file messages are properly authenticated and bound to session + */ + async _decryptFileMessage(encryptedMessageString) { + try { + const encryptedMessage = JSON.parse(encryptedMessageString); + if (encryptedMessage.type !== "encrypted_file_message") { + throw new Error("Invalid encrypted file message type"); + } + if (encryptedMessage.keyFingerprint !== this.keyFingerprint) { + throw new Error("Key fingerprint mismatch in encrypted file message"); + } + const aad = this._validateMessageAAD(encryptedMessage.aad, "file_message"); + if (!this.encryptionKey) { + throw new Error("No encryption key available for file message decryption"); + } + const decryptedData = await window.EnhancedSecureCryptoUtils.decryptDataWithAAD( + encryptedMessage.encryptedData, + this.encryptionKey, + encryptedMessage.aad + ); + return { + decryptedData, + aad + }; + } catch (error) { + this._secureLog("error", "Failed to decrypt file message", { error: error.message }); + throw new Error(`File message decryption failed: ${error.message}`); + } + } + /** + * Validates encryption keys readiness + * @param {boolean} throwError - whether to throw on not ready + * @returns {boolean} true if keys are ready + */ + _validateEncryptionKeys(throwError = true) { + const hasAllKeys = !!(this.encryptionKey && this.macKey && this.metadataKey); + if (!hasAllKeys && throwError) { + throw new Error("Encryption keys not initialized"); + } + return hasAllKeys; + } + /** + * Checks whether a message is a file-transfer message + * @param {string|object} data - message payload + * @returns {boolean} true if it's a file message + */ + _isFileMessage(data) { + if (typeof data === "string") { + try { + const parsed = JSON.parse(data); + return parsed.type && parsed.type.startsWith("file_"); + } catch { + return false; + } + } + if (typeof data === "object" && data.type) { + return data.type.startsWith("file_"); + } + return false; + } + /** + * Checks whether a message is a system message + * @param {string|object} data - message payload + * @returns {boolean} true if it's a system message + */ + _isSystemMessage(data) { + const systemTypes = [ + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_RESPONSE, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_CONFIRMED, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.PEER_DISCONNECT, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.SECURITY_UPGRADE, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_SIGNAL, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_READY + ]; + if (typeof data === "string") { + try { + const parsed = JSON.parse(data); + return systemTypes.includes(parsed.type); + } catch { + return false; + } + } + if (typeof data === "object" && data.type) { + return systemTypes.includes(data.type); + } + return false; + } + /** + * Checks whether a message is fake traffic + * @param {any} data - message payload + * @returns {boolean} true if it's a fake message + */ + _isFakeMessage(data) { + if (typeof data === "string") { + try { + const parsed = JSON.parse(data); + return parsed.type === _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE || parsed.isFakeTraffic === true; + } catch { + return false; + } + } + if (typeof data === "object" && data !== null) { + return data.type === _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE || data.isFakeTraffic === true; + } + return false; + } + /** + * Safely executes an operation with error handling + * @param {Function} operation - operation to execute + * @param {string} errorMessage - error message to log + * @param {any} fallback - default value on error + * @returns {any} operation result or fallback + */ + _withErrorHandling(operation, errorMessage, fallback = null) { + try { + return operation(); + } catch (error) { + if (this._debugMode) { + this._secureLog("error", "\u274C ${errorMessage}:", { errorType: error?.constructor?.name || "Unknown" }); + } + return fallback; + } + } + /** + * Safely executes an async operation with error handling + * @param {Function} operation - async operation + * @param {string} errorMessage - error message to log + * @param {any} fallback - default value on error + * @returns {Promise} operation result or fallback + */ + async _withAsyncErrorHandling(operation, errorMessage, fallback = null) { + try { + return await operation(); + } catch (error) { + if (this._debugMode) { + this._secureLog("error", "\u274C ${errorMessage}:", { errorType: error?.constructor?.name || "Unknown" }); + } + return fallback; + } + } + /** + * Checks rate limits + * @returns {boolean} true if allowed to proceed + */ + _checkRateLimit() { + return window.EnhancedSecureCryptoUtils.rateLimiter.checkConnectionRate(this.rateLimiterId); + } + /** + * Extracts message type from data + * @param {string|object} data - message data + * @returns {string|null} message type or null + */ + _getMessageType(data) { + if (typeof data === "string") { + try { + const parsed = JSON.parse(data); + return parsed.type || null; + } catch { + return null; + } + } + if (typeof data === "object" && data !== null) { + return data.type || null; + } + return null; + } + /** + * Resets notification flags for a new connection + */ + _resetNotificationFlags() { + this.lastSecurityLevelNotification = null; + this.verificationNotificationSent = false; + this.verificationInitiationSent = false; + this.disconnectNotificationSent = false; + this.reconnectionFailedNotificationSent = false; + this.peerDisconnectNotificationSent = false; + this.connectionClosedNotificationSent = false; + this.fakeTrafficDisabledNotificationSent = false; + this.advancedFeaturesDisabledNotificationSent = false; + this.securityUpgradeNotificationSent = false; + this.lastSecurityUpgradeStage = null; + this.securityCalculationNotificationSent = false; + this.lastSecurityCalculationLevel = null; + } + /** + * Checks whether a message was filtered out + * @param {any} result - processing result + * @returns {boolean} true if filtered + */ + _isFilteredMessage(result) { + const filteredResults = Object.values(_EnhancedSecureWebRTCManager.FILTERED_RESULTS); + return filteredResults.includes(result); + } + /** + * Enhanced log cleanup with security checks + */ + _cleanupLogs() { + if (this._logCounts.size > 500) { + this._logCounts.clear(); + this._secureLog("debug", "\u{1F9F9} Log counts cleared due to size limit"); + } + const now = Date.now(); + const maxAge = 3e5; + let suspiciousCount = 0; + for (const [key, count] of this._logCounts.entries()) { + if (count > 10) { + suspiciousCount++; + } + } + if (suspiciousCount > 20) { + this._logCounts.clear(); + this._secureLog("warn", "\u{1F6A8} Emergency log cleanup due to suspicious patterns"); + } + if (this._logSecurityViolations > 0 && suspiciousCount < 5) { + this._logSecurityViolations = Math.max(0, this._logSecurityViolations - 1); + } + if (!this._lastIVCleanupTime || Date.now() - this._lastIVCleanupTime > 3e5) { + this._cleanupOldIVs(); + this._lastIVCleanupTime = Date.now(); + } + if (!this._secureMemoryManager.memoryStats.lastCleanup || Date.now() - this._secureMemoryManager.memoryStats.lastCleanup > 6e5) { + this._performPeriodicMemoryCleanup(); + this._secureMemoryManager.memoryStats.lastCleanup = Date.now(); + } + } + /** + * Secure logging stats with sensitive data protection + */ + _getLoggingStats() { + const stats = { + isProductionMode: this._isProductionMode, + debugMode: this._debugMode, + currentLogLevel: this._currentLogLevel, + logCountsSize: this._logCounts.size, + maxLogCount: this._maxLogCount, + securityViolations: this._logSecurityViolations || 0, + maxSecurityViolations: this._maxLogSecurityViolations || 3, + systemStatus: this._currentLogLevel === -1 ? "DISABLED" : "ACTIVE" + }; + const sanitizedStats = {}; + for (const [key, value] of Object.entries(stats)) { + if (typeof value === "string" && this._containsSensitiveContent(value)) { + sanitizedStats[key] = "[SENSITIVE_DATA_REDACTED]"; + } else { + sanitizedStats[key] = value; + } + } + return sanitizedStats; + } + /** + * Enhanced emergency logging disable with cleanup + */ + _emergencyDisableLogging() { + this._currentLogLevel = -1; + this._logCounts.clear(); + if (this._logSecurityViolations) { + this._logSecurityViolations = 0; + } + this._secureLog = () => { + if (arguments[0] === "error" && this._originalConsole?.error) { + this._originalConsole.error("\u{1F6A8} SECURITY: Logging system disabled - potential data exposure prevented"); + } + }; + this._originalSanitizeString = this._sanitizeString; + this._originalSanitizeLogData = this._sanitizeLogData; + this._originalAuditLogMessage = this._auditLogMessage; + this._originalContainsSensitiveContent = this._containsSensitiveContent; + this._sanitizeString = () => "[LOGGING_DISABLED]"; + this._sanitizeLogData = () => ({ error: "LOGGING_DISABLED" }); + this._auditLogMessage = () => false; + this._containsSensitiveContent = () => true; + if (typeof window.gc === "function") { + try { + window.gc(); + } catch (e) { + } + } + this._originalConsole?.error?.("\u{1F6A8} CRITICAL: Secure logging system disabled due to potential data exposure"); + } + /** + * Reset logging system after emergency shutdown + * Use this function to restore normal logging functionality + */ + _resetLoggingSystem() { + this._secureLog("info", "\u{1F527} Resetting logging system after emergency shutdown"); + this._sanitizeString = this._originalSanitizeString || ((str) => str); + this._sanitizeLogData = this._originalSanitizeLogData || ((data) => data); + this._auditLogMessage = this._originalAuditLogMessage || (() => true); + this._containsSensitiveContent = this._originalContainsSensitiveContent || (() => false); + this._logSecurityViolations = 0; + this._secureLog("info", "\u2705 Logging system reset successfully"); + } + /** + * Enhanced audit function for log message security + */ + _auditLogMessage(message, data) { + if (!data || typeof data !== "object") return true; + const dataString = JSON.stringify(data); + if (this._containsSensitiveContent(message)) { + this._emergencyDisableLogging(); + this._originalConsole?.error?.("\u{1F6A8} SECURITY BREACH: Sensitive content detected in log message"); + return false; + } + if (this._containsSensitiveContent(dataString)) { + this._emergencyDisableLogging(); + this._originalConsole?.error?.("\u{1F6A8} SECURITY BREACH: Sensitive content detected in log data"); + return false; + } + const dangerousPatterns = [ + "secret", + "token", + "password", + "credential", + "auth", + "fingerprint", + "salt", + "signature", + "private_key", + "api_key", + "private", + "encryption", + "mac", + "metadata", + "session", + "jwt", + "bearer", + "key", + "hash", + "digest", + "nonce", + "iv", + "cipher" + ]; + const dataStringLower = dataString.toLowerCase(); + for (const pattern of dangerousPatterns) { + if (dataStringLower.includes(pattern) && !this._safeFieldsWhitelist.has(pattern)) { + this._emergencyDisableLogging(); + this._originalConsole?.error?.(`\u{1F6A8} SECURITY BREACH: Dangerous pattern detected in log: ${pattern}`); + return false; + } + } + for (const [key, value] of Object.entries(data)) { + if (typeof value === "string" && this._hasHighEntropy(value)) { + this._emergencyDisableLogging(); + this._originalConsole?.error?.(`\u{1F6A8} SECURITY BREACH: High entropy value detected in log field: ${key}`); + return false; + } + } + return true; + } + initializeFileTransfer() { + try { + this._secureLog("info", "\u{1F527} Initializing Enhanced Secure File Transfer system..."); + if (this.fileTransferSystem) { + this._secureLog("info", "\u2705 File transfer system already initialized"); + return; + } + const channelReady = !!(this.dataChannel && this.dataChannel.readyState === "open"); + if (!channelReady) { + this._secureLog("warn", "\u26A0\uFE0F Data channel not open, deferring file transfer initialization"); + if (this.dataChannel) { + const initHandler = () => { + this._secureLog("info", "\u{1F504} DataChannel opened, initializing file transfer..."); + this.initializeFileTransfer(); + }; + this.dataChannel.addEventListener("open", initHandler, { once: true }); + } + return; + } + if (!this.isVerified) { + this._secureLog("warn", "\u26A0\uFE0F Connection not verified yet, deferring file transfer initialization"); + setTimeout(() => this.initializeFileTransfer(), 500); + return; + } + if (this.fileTransferSystem) { + this._secureLog("info", "\u{1F9F9} Cleaning up existing file transfer system"); + this.fileTransferSystem.cleanup(); + this.fileTransferSystem = null; + } + if (!this.encryptionKey || !this.macKey) { + this._secureLog("warn", "\u26A0\uFE0F Encryption keys not ready, deferring file transfer initialization"); + setTimeout(() => this.initializeFileTransfer(), 1e3); + return; + } + const safeOnComplete = (summary) => { + try { + this._secureLog("info", "\u{1F3C1} Sender transfer summary", { summary }); + if (this.onFileProgress) { + this.onFileProgress({ type: "complete", ...summary }); + } + } catch (e) { + this._secureLog("warn", "\u26A0\uFE0F onComplete handler failed:", { details: e.message }); + } + }; + this.fileTransferSystem = new EnhancedSecureFileTransfer( + this, + this.onFileProgress || null, + safeOnComplete, + this.onFileError || null, + this.onFileReceived || null + ); + this._fileTransferActive = true; + this._secureLog("info", "\u2705 Enhanced Secure File Transfer system initialized successfully"); + const status = this.fileTransferSystem.getSystemStatus(); + this._secureLog("info", "\u{1F50D} File transfer system status after init", { status }); + } catch (error) { + this._secureLog("error", "\u274C Failed to initialize file transfer system", { errorType: error.constructor.name }); + this.fileTransferSystem = null; + this._fileTransferActive = false; + } + } + // ============================================ + // ENHANCED SECURITY INITIALIZATION + // ============================================ + async initializeEnhancedSecurity() { + try { + await this.generateNestedEncryptionKey(); + if (this.decoyChannelConfig.enabled) { + this.initializeDecoyChannels(); + } + if (this.fakeTrafficConfig.enabled) { + this.startFakeTrafficGeneration(); + } + } catch (error) { + this._secureLog("error", "\u274C Failed to initialize enhanced security", { errorType: error.constructor.name }); + } + } + // Generate fingerprint mask for anti-fingerprinting with enhanced randomization + generateFingerprintMask() { + const cryptoRandom = crypto.getRandomValues(new Uint8Array(128)); + const mask = { + timingOffset: cryptoRandom[0] % 1e3 + cryptoRandom[1] % 500, + // 0-1500ms + sizeVariation: (cryptoRandom[2] % 50 + 75) / 100, + // 0.75 to 1.25 + noisePattern: Array.from(crypto.getRandomValues(new Uint8Array(64))), + // Increased size + headerVariations: [ + "X-Client-Version", + "X-Session-ID", + "X-Request-ID", + "X-Timestamp", + "X-Signature", + "X-Secure", + "X-Encrypted", + "X-Protected", + "X-Safe", + "X-Anonymous", + "X-Private" + ], + noiseIntensity: cryptoRandom[3] % 100 + 50, + // 50-150% + sizeMultiplier: (cryptoRandom[4] % 50 + 75) / 100, + // 0.75-1.25 + timingVariation: cryptoRandom[5] % 1e3 + 100 + // 100-1100ms + }; + return mask; + } + // Security configuration for session type + configureSecurityForSession(sessionType, securityLevel) { + this._secureLog("info", `\u{1F527} Configuring security for ${sessionType} session (${securityLevel} level)`); + this.currentSessionType = sessionType; + this.currentSecurityLevel = securityLevel; + if (window.sessionManager && window.sessionManager.isFeatureAllowedForSession) { + this.sessionConstraints = {}; + Object.keys(this.securityFeatures).forEach((feature) => { + this.sessionConstraints[feature] = window.sessionManager.isFeatureAllowedForSession(sessionType, feature); + }); + this.applySessionConstraints(); + this._secureLog("info", `\u2705 Security configured for ${sessionType}`, { constraints: this.sessionConstraints }); + if (!this._validateCryptographicSecurity()) { + this._secureLog("error", "\u{1F6A8} CRITICAL: Cryptographic security validation failed after session configuration"); + if (this.onStatusChange) { + this.onStatusChange("security_breach", { + type: "crypto_security_failure", + sessionType, + message: "Cryptographic security validation failed after session configuration" + }); + } + } + this.notifySecurityLevel(); + setTimeout(() => { + this.calculateAndReportSecurityLevel(); + }, _EnhancedSecureWebRTCManager.TIMEOUTS.SECURITY_CALC_DELAY); + } else { + this._secureLog("warn", "\u26A0\uFE0F Session manager not available, using default security"); + } + } + // Applying session restrictions + applySessionConstraints() { + if (!this.sessionConstraints) return; + Object.keys(this.sessionConstraints).forEach((feature) => { + const allowed = this.sessionConstraints[feature]; + if (!allowed && this.securityFeatures[feature]) { + this._secureLog("info", `\u{1F512} Disabling ${feature} for ${this.currentSessionType} session`); + this.securityFeatures[feature] = false; + switch (feature) { + case "hasFakeTraffic": + this.fakeTrafficConfig.enabled = false; + this.stopFakeTrafficGeneration(); + break; + case "hasDecoyChannels": + this.decoyChannelConfig.enabled = false; + this.cleanupDecoyChannels(); + break; + case "hasPacketReordering": + this.reorderingConfig.enabled = false; + this.packetBuffer.clear(); + break; + case "hasAntiFingerprinting": + this.antiFingerprintingConfig.enabled = false; + break; + case "hasMessageChunking": + this.chunkingConfig.enabled = false; + break; + } + } else if (allowed && !this.securityFeatures[feature]) { + this._secureLog("info", `\u{1F513} Enabling ${feature} for ${this.currentSessionType} session`); + this.securityFeatures[feature] = true; + switch (feature) { + case "hasFakeTraffic": + this.fakeTrafficConfig.enabled = true; + if (this.isConnected()) { + this.startFakeTrafficGeneration(); + } + break; + case "hasDecoyChannels": + this.decoyChannelConfig.enabled = true; + if (this.isConnected()) { + this.initializeDecoyChannels(); + } + break; + case "hasPacketReordering": + this.reorderingConfig.enabled = true; + break; + case "hasAntiFingerprinting": + this.antiFingerprintingConfig.enabled = true; + break; + case "hasMessageChunking": + this.chunkingConfig.enabled = true; + break; + } + } + }); + } + deliverMessageToUI(message, type = "received") { + try { + this._secureLog("debug", "\u{1F4E4} deliverMessageToUI called", { + message, + type, + messageType: typeof message, + hasOnMessage: !!this.onMessage + }); + if (typeof message === "object" && message.type) { + const blockedTypes = [ + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_START, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_RESPONSE, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_CHUNK, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.CHUNK_CONFIRMATION, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_COMPLETE, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_ERROR, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_RESPONSE, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_CONFIRMED, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.PEER_DISCONNECT, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_SIGNAL, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_READY, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.SECURITY_UPGRADE + ]; + if (blockedTypes.includes(message.type)) { + if (this._debugMode) { + this._secureLog("warn", `\u{1F6D1} Blocked system/file message from UI: ${message.type}`); + } + return; + } + } + if (typeof message === "string" && message.trim().startsWith("{")) { + try { + const parsedMessage = JSON.parse(message); + if (parsedMessage.type) { + const blockedTypes = [ + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_START, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_RESPONSE, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_CHUNK, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.CHUNK_CONFIRMATION, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_COMPLETE, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_ERROR, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_RESPONSE, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_CONFIRMED, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.PEER_DISCONNECT, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_SIGNAL, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_READY, + _EnhancedSecureWebRTCManager.MESSAGE_TYPES.SECURITY_UPGRADE + ]; + if (blockedTypes.includes(parsedMessage.type)) { + if (this._debugMode) { + this._secureLog("warn", `\u{1F6D1} Blocked system/file message from UI (string): ${parsedMessage.type}`); + } + return; + } + } + } catch (parseError) { + } + } + if (this.onMessage) { + this._secureLog("debug", "\u{1F4E4} Calling this.onMessage callback", { message, type }); + this.onMessage(message, type); + } else { + this._secureLog("warn", "\u26A0\uFE0F this.onMessage callback is null or undefined"); + } + } catch (err) { + this._secureLog("error", "\u274C Failed to deliver message to UI:", { errorType: err?.constructor?.name || "Unknown" }); + } + } + // Security Level Notification + notifySecurityLevel() { + if (this.lastSecurityLevelNotification === this.currentSecurityLevel) { + return; + } + this.lastSecurityLevelNotification = this.currentSecurityLevel; + const levelMessages = { + "basic": "\u{1F512} Basic Security Active - Demo session with essential protection", + "enhanced": "\u{1F510} Enhanced Security Active - Paid session with advanced protection", + "maximum": "\u{1F6E1}\uFE0F Maximum Security Active - Premium session with complete protection" + }; + const message = levelMessages[this.currentSecurityLevel] || levelMessages["basic"]; + if (this.onMessage) { + this.deliverMessageToUI(message, "system"); + } + if (this.currentSecurityLevel !== "basic" && this.onMessage) { + const activeFeatures = Object.entries(this.securityFeatures).filter(([key, value]) => value === true).map(([key]) => key.replace("has", "").replace(/([A-Z])/g, " $1").trim().toLowerCase()).slice(0, 5); + this.deliverMessageToUI(`\u{1F527} Active: ${activeFeatures.join(", ")}...`, "system"); + } + } + // Cleaning decoy channels + cleanupDecoyChannels() { + for (const [channelName, timer] of this.decoyTimers.entries()) { + clearTimeout(timer); + } + this.decoyTimers.clear(); + for (const [channelName, channel] of this.decoyChannels.entries()) { + if (channel.readyState === "open") { + channel.close(); + } + } + this.decoyChannels.clear(); + this._secureLog("info", "\u{1F9F9} Decoy channels cleaned up"); + } + // ============================================ + // 1. NESTED ENCRYPTION LAYER + // ============================================ + async generateNestedEncryptionKey() { + try { + this.nestedEncryptionKey = await crypto.subtle.generateKey( + { name: "AES-GCM", length: 256 }, + false, + ["encrypt", "decrypt"] + ); + } catch (error) { + this._secureLog("error", "\u274C Failed to generate nested encryption key:", { errorType: error?.constructor?.name || "Unknown" }); + throw error; + } + } + async applyNestedEncryption(data) { + if (!this.nestedEncryptionKey || !this.securityFeatures.hasNestedEncryption) { + return data; + } + try { + const uniqueIV = this._generateSecureIV( + _EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE, + "nestedEncryption" + ); + const encrypted = await crypto.subtle.encrypt( + { name: "AES-GCM", iv: uniqueIV }, + this.nestedEncryptionKey, + data + ); + const result = new Uint8Array(_EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE + encrypted.byteLength); + result.set(uniqueIV, 0); + result.set(new Uint8Array(encrypted), _EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE); + this._secureLog("debug", "\u2705 Nested encryption applied with secure IV", { + ivSize: uniqueIV.length, + dataSize: data.byteLength, + encryptedSize: encrypted.byteLength + }); + return result.buffer; + } catch (error) { + this._secureLog("error", "\u274C Nested encryption failed:", { + errorType: error?.constructor?.name || "Unknown", + errorMessage: error?.message || "Unknown error" + }); + if (error.message.includes("emergency mode")) { + this.securityFeatures.hasNestedEncryption = false; + this._secureLog("warn", "\u26A0\uFE0F Nested encryption disabled due to IV emergency mode"); + } + return data; + } + } + async removeNestedEncryption(data) { + if (!this.nestedEncryptionKey || !this.securityFeatures.hasNestedEncryption) { + return data; + } + if (!(data instanceof ArrayBuffer) || data.byteLength < _EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE + 16) { + if (this._debugMode) { + this._secureLog("debug", "\u{1F4DD} Data not encrypted or too short for nested decryption (need IV + minimum encrypted data)"); + } + return data; + } + try { + const dataArray = new Uint8Array(data); + const iv = dataArray.slice(0, _EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE); + const encryptedData = dataArray.slice(_EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE); + if (encryptedData.length === 0) { + if (this._debugMode) { + this._secureLog("debug", "\u{1F4DD} No encrypted data found"); + } + return data; + } + const decrypted = await crypto.subtle.decrypt( + { name: "AES-GCM", iv }, + this.nestedEncryptionKey, + encryptedData + ); + return decrypted; + } catch (error) { + if (error.name === "OperationError") { + if (this._debugMode) { + this._secureLog("debug", "\u{1F4DD} Data not encrypted with nested encryption, skipping..."); + } + } else { + if (this._debugMode) { + this._secureLog("warn", "\u26A0\uFE0F Nested decryption failed:", { details: error.message }); + } + } + return data; + } + } + // ============================================ + // 2. PACKET PADDING + // ============================================ + applyPacketPadding(data) { + if (!this.securityFeatures.hasPacketPadding) { + return data; + } + try { + const originalSize = data.byteLength; + let paddingSize; + if (this.paddingConfig.useRandomPadding) { + paddingSize = Math.floor(Math.random() * (this.paddingConfig.maxPadding - this.paddingConfig.minPadding + 1)) + this.paddingConfig.minPadding; + } else { + paddingSize = this.paddingConfig.minPadding; + } + const padding = crypto.getRandomValues(new Uint8Array(paddingSize)); + const paddedData = new Uint8Array(originalSize + paddingSize + 4); + const sizeView = new DataView(paddedData.buffer, 0, 4); + sizeView.setUint32(0, originalSize, false); + paddedData.set(new Uint8Array(data), 4); + paddedData.set(padding, 4 + originalSize); + return paddedData.buffer; + } catch (error) { + this._secureLog("error", "\u274C Packet padding failed:", { errorType: error?.constructor?.name || "Unknown" }); + return data; + } + } + removePacketPadding(data) { + if (!this.securityFeatures.hasPacketPadding) { + return data; + } + try { + const dataArray = new Uint8Array(data); + if (dataArray.length < 5) { + if (this._debugMode) { + this._secureLog("warn", "\u26A0\uFE0F Data too short for packet padding removal, skipping"); + } + return data; + } + const sizeView = new DataView(dataArray.buffer, 0, 4); + const originalSize = sizeView.getUint32(0, false); + if (originalSize <= 0 || originalSize > dataArray.length - 4) { + if (this._debugMode) { + this._secureLog("warn", "\u26A0\uFE0F Invalid packet padding size, skipping removal"); + } + return data; + } + const originalData = dataArray.slice(4, 4 + originalSize); + return originalData.buffer; + } catch (error) { + if (this._debugMode) { + this._secureLog("error", "\u274C Packet padding removal failed:", { errorType: error?.constructor?.name || "Unknown" }); + } + return data; + } + } + // ============================================ + // 3. FAKE TRAFFIC GENERATION + // ============================================ + startFakeTrafficGeneration() { + if (!this.fakeTrafficConfig.enabled || !this.isConnected()) { + return; + } + if (this.fakeTrafficTimer) { + this._secureLog("warn", "\u26A0\uFE0F Fake traffic generation already running"); + return; + } + const sendFakeMessage = async () => { + if (!this.isConnected()) { + this.stopFakeTrafficGeneration(); + return; + } + try { + const fakeMessage = this.generateFakeMessage(); + await this.sendFakeMessage(fakeMessage); + const nextInterval = this.fakeTrafficConfig.randomDecoyIntervals ? Math.random() * (this.fakeTrafficConfig.maxInterval - this.fakeTrafficConfig.minInterval) + this.fakeTrafficConfig.minInterval : this.fakeTrafficConfig.minInterval; + const safeInterval = Math.max(nextInterval, _EnhancedSecureWebRTCManager.TIMEOUTS.FAKE_TRAFFIC_MIN_INTERVAL); + this.fakeTrafficTimer = setTimeout(sendFakeMessage, safeInterval); + } catch (error) { + if (this._debugMode) { + this._secureLog("error", "\u274C Fake traffic generation failed:", { errorType: error?.constructor?.name || "Unknown" }); + } + this.stopFakeTrafficGeneration(); + } + }; + const initialDelay = Math.random() * this.fakeTrafficConfig.maxInterval + _EnhancedSecureWebRTCManager.TIMEOUTS.DECOY_INITIAL_DELAY; + this.fakeTrafficTimer = setTimeout(sendFakeMessage, initialDelay); + } + stopFakeTrafficGeneration() { + if (this.fakeTrafficTimer) { + clearTimeout(this.fakeTrafficTimer); + this.fakeTrafficTimer = null; + } + } + generateFakeMessage() { + const pattern = this.fakeTrafficConfig.patterns[Math.floor(Math.random() * this.fakeTrafficConfig.patterns.length)]; + const size = Math.floor(Math.random() * (this.fakeTrafficConfig.maxSize - this.fakeTrafficConfig.minSize + 1)) + this.fakeTrafficConfig.minSize; + const fakeData = crypto.getRandomValues(new Uint8Array(size)); + return { + type: _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE, + pattern, + data: Array.from(fakeData).map((b) => b.toString(16).padStart(2, "0")).join(""), + timestamp: Date.now(), + size, + isFakeTraffic: true, + source: "fake_traffic_generator", + fakeId: crypto.getRandomValues(new Uint32Array(1))[0].toString(36) + }; + } + // ============================================ + // EMERGENCY SHUT-OFF OF ADVANCED FUNCTIONS + // ============================================ + emergencyDisableAdvancedFeatures() { + this._secureLog("error", "\u{1F6A8} Emergency disabling advanced security features due to errors"); + this.securityFeatures.hasNestedEncryption = false; + this.securityFeatures.hasPacketReordering = false; + this.securityFeatures.hasAntiFingerprinting = false; + this.reorderingConfig.enabled = false; + this.antiFingerprintingConfig.enabled = false; + this.packetBuffer.clear(); + this.emergencyDisableFakeTraffic(); + this._secureLog("info", "\u2705 Advanced features disabled, keeping basic encryption"); + if (!this.advancedFeaturesDisabledNotificationSent) { + this.advancedFeaturesDisabledNotificationSent = true; + if (this.onMessage) { + this.deliverMessageToUI("\u{1F6A8} Advanced security features temporarily disabled due to compatibility issues", "system"); + } + } + } + async sendFakeMessage(fakeMessage) { + if (!this._validateConnection(false)) { + return; + } + try { + this._secureLog("debug", "\u{1F3AD} Sending fake message", { + hasPattern: !!fakeMessage.pattern, + sizeRange: fakeMessage.size > 100 ? "large" : "small" + }); + const fakeData = JSON.stringify({ + ...fakeMessage, + type: _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE, + isFakeTraffic: true, + timestamp: Date.now() + }); + const fakeBuffer = new TextEncoder().encode(fakeData); + const encryptedFake = await this.applySecurityLayers(fakeBuffer, true); + this.dataChannel.send(encryptedFake); + this._secureLog("debug", "\u{1F3AD} Fake message sent successfully", { + pattern: fakeMessage.pattern + }); + } catch (error) { + this._secureLog("error", "\u274C Failed to send fake message", { + error: error.message + }); + } + } + checkFakeTrafficStatus() { + const status = { + fakeTrafficEnabled: this.securityFeatures.hasFakeTraffic, + fakeTrafficConfigEnabled: this.fakeTrafficConfig.enabled, + timerActive: !!this.fakeTrafficTimer, + patterns: this.fakeTrafficConfig.patterns, + intervals: { + min: this.fakeTrafficConfig.minInterval, + max: this.fakeTrafficConfig.maxInterval + } + }; + if (this._debugMode) { + this._secureLog("info", "\u{1F3AD} Fake Traffic Status", { status }); + } + return status; + } + emergencyDisableFakeTraffic() { + if (this._debugMode) { + this._secureLog("error", "\u{1F6A8} Emergency disabling fake traffic"); + } + this.securityFeatures.hasFakeTraffic = false; + this.fakeTrafficConfig.enabled = false; + this.stopFakeTrafficGeneration(); + if (this._debugMode) { + this._secureLog("info", "\u2705 Fake traffic disabled"); + } + if (!this.fakeTrafficDisabledNotificationSent) { + this.fakeTrafficDisabledNotificationSent = true; + if (this.onMessage) { + this.deliverMessageToUI("\u{1F6A8} Fake traffic emergency disabled", "system"); + } + } + } + async _applySecurityLayersWithoutMutex(data, isFakeMessage = false) { + try { + let processedData = data; + if (isFakeMessage) { + if (this.encryptionKey && typeof processedData === "string") { + processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey); + } + return processedData; + } + if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey && processedData instanceof ArrayBuffer) { + processedData = await this.applyNestedEncryption(processedData); + } + if (this.securityFeatures.hasPacketReordering && this.reorderingConfig?.enabled && processedData instanceof ArrayBuffer) { + processedData = this.applyPacketReordering(processedData); + } + if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) { + processedData = this.applyPacketPadding(processedData); + } + if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) { + processedData = this.applyAntiFingerprinting(processedData); + } + if (this.encryptionKey && typeof processedData === "string") { + processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey); + } + return processedData; + } catch (error) { + this._secureLog("error", "\u274C Error in applySecurityLayersWithoutMutex:", { errorType: error?.constructor?.name || "Unknown" }); + return data; + } + } + // ============================================ + // 4. MESSAGE CHUNKING + // ============================================ + async processChunkedMessage(chunkData) { + try { + if (!this.chunkingConfig.addChunkHeaders) { + return this.processMessage(chunkData); + } + const chunkArray = new Uint8Array(chunkData); + if (chunkArray.length < 16) { + return this.processMessage(chunkData); + } + const headerView = new DataView(chunkArray.buffer, 0, 16); + const messageId = headerView.getUint32(0, false); + const chunkIndex = headerView.getUint32(4, false); + const totalChunks = headerView.getUint32(8, false); + const chunkSize = headerView.getUint32(12, false); + const chunk = chunkArray.slice(16, 16 + chunkSize); + if (!this.chunkQueue[messageId]) { + this.chunkQueue[messageId] = { + chunks: new Array(totalChunks), + received: 0, + timestamp: Date.now() + }; + } + const messageBuffer = this.chunkQueue[messageId]; + messageBuffer.chunks[chunkIndex] = chunk; + messageBuffer.received++; + this._secureLog("debug", `\u{1F4E6} Received chunk ${chunkIndex + 1}/${totalChunks} for message ${messageId}`); + if (messageBuffer.received === totalChunks) { + const totalSize = messageBuffer.chunks.reduce((sum, chunk2) => sum + chunk2.length, 0); + const combinedData = new Uint8Array(totalSize); + let offset = 0; + for (const chunk2 of messageBuffer.chunks) { + combinedData.set(chunk2, offset); + offset += chunk2.length; + } + await this.processMessage(combinedData.buffer); + delete this.chunkQueue[messageId]; + this._secureLog("info", `\u{1F4E6} Chunked message ${messageId} reassembled and processed`); + } + } catch (error) { + this._secureLog("error", "\u274C Chunked message processing failed:", { errorType: error?.constructor?.name || "Unknown" }); + } + } + // ============================================ + // 5. DECOY CHANNELS + // ============================================ + initializeDecoyChannels() { + if (!this.decoyChannelConfig.enabled || !this.peerConnection) { + return; + } + if (this.decoyChannels.size > 0) { + this._secureLog("warn", "\u26A0\uFE0F Decoy channels already initialized, skipping..."); + return; + } + try { + const numDecoyChannels = Math.min( + this.decoyChannelConfig.maxDecoyChannels, + this.decoyChannelConfig.decoyChannelNames.length + ); + for (let i = 0; i < numDecoyChannels; i++) { + const channelName = this.decoyChannelConfig.decoyChannelNames[i]; + const decoyChannel = this.peerConnection.createDataChannel(channelName, { + ordered: Math.random() > 0.5, + maxRetransmits: Math.floor(Math.random() * 3) + }); + this.setupDecoyChannel(decoyChannel, channelName); + this.decoyChannels.set(channelName, decoyChannel); + } + if (this._debugMode) { + this._secureLog("info", `\u{1F3AD} Initialized ${numDecoyChannels} decoy channels`); + } + } catch (error) { + if (this._debugMode) { + this._secureLog("error", "\u274C Failed to initialize decoy channels:", { errorType: error?.constructor?.name || "Unknown" }); + } + } + } + setupDecoyChannel(channel, channelName) { + channel.onopen = () => { + if (this._debugMode) { + this._secureLog("debug", `\u{1F3AD} Decoy channel "${channelName}" opened`); + } + this.startDecoyTraffic(channel, channelName); + }; + channel.onmessage = (event) => { + if (this._debugMode) { + this._secureLog("debug", `\u{1F3AD} Received decoy message on "${channelName}": ${event.data?.length || "undefined"} bytes`); + } + }; + channel.onclose = () => { + if (this._debugMode) { + this._secureLog("debug", `\u{1F3AD} Decoy channel "${channelName}" closed`); + } + this.stopDecoyTraffic(channelName); + }; + channel.onerror = (error) => { + if (this._debugMode) { + this._secureLog("error", `\u274C Decoy channel "${channelName}" error`, { error: error.message }); + } + }; + } + startDecoyTraffic(channel, channelName) { + const sendDecoyData = async () => { + if (channel.readyState !== "open") { + return; + } + try { + const decoyData = this.generateDecoyData(channelName); + channel.send(decoyData); + const interval = this.decoyChannelConfig.randomDecoyIntervals ? Math.random() * 15e3 + 1e4 : 2e4; + this.decoyTimers.set(channelName, setTimeout(() => sendDecoyData(), interval)); + } catch (error) { + if (this._debugMode) { + this._secureLog("error", `\u274C Failed to send decoy data on "${channelName}"`, { error: error.message }); + } + } + }; + const initialDelay = Math.random() * 1e4 + 5e3; + this.decoyTimers.set(channelName, setTimeout(() => sendDecoyData(), initialDelay)); + } + stopDecoyTraffic(channelName) { + const timer = this.decoyTimers.get(channelName); + if (timer) { + clearTimeout(timer); + this.decoyTimers.delete(channelName); + } + } + generateDecoyData(channelName) { + const decoyTypes = { + "sync": () => JSON.stringify({ + type: "sync", + timestamp: Date.now(), + sequence: Math.floor(Math.random() * 1e3), + data: Array.from(crypto.getRandomValues(new Uint8Array(32))).map((b) => b.toString(16).padStart(2, "0")).join("") + }), + "status": () => JSON.stringify({ + type: "status", + status: ["online", "away", "busy"][Math.floor(Math.random() * 3)], + uptime: Math.floor(Math.random() * 3600), + data: Array.from(crypto.getRandomValues(new Uint8Array(16))).map((b) => b.toString(16).padStart(2, "0")).join("") + }), + "heartbeat": () => JSON.stringify({ + type: "heartbeat", + timestamp: Date.now(), + data: Array.from(crypto.getRandomValues(new Uint8Array(24))).map((b) => b.toString(16).padStart(2, "0")).join("") + }), + "metrics": () => JSON.stringify({ + type: "metrics", + cpu: Math.random() * 100, + memory: Math.random() * 100, + network: Math.random() * 1e3, + data: Array.from(crypto.getRandomValues(new Uint8Array(20))).map((b) => b.toString(16).padStart(2, "0")).join("") + }), + "debug": () => JSON.stringify({ + type: "debug", + level: ["info", "warn", "error"][Math.floor(Math.random() * 3)], + message: "Debug message", + data: Array.from(crypto.getRandomValues(new Uint8Array(28))).map((b) => b.toString(16).padStart(2, "0")).join("") + }) + }; + return decoyTypes[channelName] ? decoyTypes[channelName]() : Array.from(crypto.getRandomValues(new Uint8Array(64))).map((b) => b.toString(16).padStart(2, "0")).join(""); + } + // ============================================ + // 6. PACKET REORDERING PROTECTION + // ============================================ + addReorderingHeaders(data) { + if (!this.reorderingConfig.enabled) { + return data; + } + try { + const dataArray = new Uint8Array(data); + const headerSize = this.reorderingConfig.useTimestamps ? 12 : 8; + const header = new ArrayBuffer(headerSize); + const headerView = new DataView(header); + if (this.reorderingConfig.useSequenceNumbers) { + headerView.setUint32(0, this.sequenceNumber++, false); + } + if (this.reorderingConfig.useTimestamps) { + headerView.setUint32(4, Date.now(), false); + } + headerView.setUint32(this.reorderingConfig.useTimestamps ? 8 : 4, dataArray.length, false); + const result = new Uint8Array(headerSize + dataArray.length); + result.set(new Uint8Array(header), 0); + result.set(dataArray, headerSize); + return result.buffer; + } catch (error) { + this._secureLog("error", "\u274C Failed to add reordering headers:", { errorType: error?.constructor?.name || "Unknown" }); + return data; + } + } + async processReorderedPacket(data) { + if (!this.reorderingConfig.enabled) { + return this.processMessage(data); + } + try { + const dataArray = new Uint8Array(data); + const headerSize = this.reorderingConfig.useTimestamps ? 12 : 8; + if (dataArray.length < headerSize) { + if (this._debugMode) { + this._secureLog("warn", "\u26A0\uFE0F Data too short for reordering headers, processing directly"); + } + return this.processMessage(data); + } + const headerView = new DataView(dataArray.buffer, 0, headerSize); + let sequence = 0; + let timestamp = 0; + let dataSize = 0; + if (this.reorderingConfig.useSequenceNumbers) { + sequence = headerView.getUint32(0, false); + } + if (this.reorderingConfig.useTimestamps) { + timestamp = headerView.getUint32(4, false); + } + dataSize = headerView.getUint32(this.reorderingConfig.useTimestamps ? 8 : 4, false); + if (dataSize > dataArray.length - headerSize || dataSize <= 0) { + if (this._debugMode) { + this._secureLog("warn", "\u26A0\uFE0F Invalid reordered packet data size, processing directly"); + } + return this.processMessage(data); + } + const actualData = dataArray.slice(headerSize, headerSize + dataSize); + try { + const textData = new TextDecoder().decode(actualData); + const content = JSON.parse(textData); + if (content.type === "fake" || content.isFakeTraffic === true) { + if (this._debugMode) { + this._secureLog("warn", `\u{1F3AD} BLOCKED: Reordered fake message: ${content.pattern || "unknown"}`); + } + return; + } + } catch (e) { + } + this.packetBuffer.set(sequence, { + data: actualData.buffer, + timestamp: timestamp || Date.now() + }); + await this.processOrderedPackets(); + } catch (error) { + this._secureLog("error", "\u274C Failed to process reordered packet:", { errorType: error?.constructor?.name || "Unknown" }); + return this.processMessage(data); + } + } + // ============================================ + // IMPROVED PROCESSORDEREDPACKETS with filtering + // ============================================ + async processOrderedPackets() { + const now = Date.now(); + const timeout = this.reorderingConfig.reorderTimeout; + while (true) { + const nextSequence = this.lastProcessedSequence + 1; + const packet = this.packetBuffer.get(nextSequence); + if (!packet) { + const oldestPacket = this.findOldestPacket(); + if (oldestPacket && now - oldestPacket.timestamp > timeout) { + this._secureLog("warn", "\u26A0\uFE0F Packet ${oldestPacket.sequence} timed out, processing out of order"); + try { + const textData = new TextDecoder().decode(oldestPacket.data); + const content = JSON.parse(textData); + if (content.type === "fake" || content.isFakeTraffic === true) { + this._secureLog("warn", `\u{1F3AD} BLOCKED: Timed out fake message: ${content.pattern || "unknown"}`); + this.packetBuffer.delete(oldestPacket.sequence); + this.lastProcessedSequence = oldestPacket.sequence; + continue; + } + } catch (e) { + } + await this.processMessage(oldestPacket.data); + this.packetBuffer.delete(oldestPacket.sequence); + this.lastProcessedSequence = oldestPacket.sequence; + } else { + break; + } + } else { + try { + const textData = new TextDecoder().decode(packet.data); + const content = JSON.parse(textData); + if (content.type === "fake" || content.isFakeTraffic === true) { + this._secureLog("warn", `\u{1F3AD} BLOCKED: Ordered fake message: ${content.pattern || "unknown"}`); + this.packetBuffer.delete(nextSequence); + this.lastProcessedSequence = nextSequence; + continue; + } + } catch (e) { + } + await this.processMessage(packet.data); + this.packetBuffer.delete(nextSequence); + this.lastProcessedSequence = nextSequence; + } + } + this.cleanupOldPackets(now, timeout); + } + findOldestPacket() { + let oldest = null; + for (const [sequence, packet] of this.packetBuffer.entries()) { + if (!oldest || packet.timestamp < oldest.timestamp) { + oldest = { sequence, ...packet }; + } + } + return oldest; + } + cleanupOldPackets(now, timeout) { + for (const [sequence, packet] of this.packetBuffer.entries()) { + if (now - packet.timestamp > timeout) { + this._secureLog("warn", "\u26A0\uFE0F \u{1F5D1}\uFE0F Removing timed out packet ${sequence}"); + this.packetBuffer.delete(sequence); + } + } + } + // ============================================ + // 7. ANTI-FINGERPRINTING + // ============================================ + applyAntiFingerprinting(data) { + if (!this.antiFingerprintingConfig.enabled) { + return data; + } + try { + let processedData = data; + if (this.antiFingerprintingConfig.addNoise) { + processedData = this.addNoise(processedData); + } + if (this.antiFingerprintingConfig.randomizeSizes) { + processedData = this.randomizeSize(processedData); + } + if (this.antiFingerprintingConfig.maskPatterns) { + processedData = this.maskPatterns(processedData); + } + if (this.antiFingerprintingConfig.useRandomHeaders) { + processedData = this.addRandomHeaders(processedData); + } + return processedData; + } catch (error) { + this._secureLog("error", "\u274C Anti-fingerprinting failed:", { errorType: error?.constructor?.name || "Unknown" }); + return data; + } + } + addNoise(data) { + const dataArray = new Uint8Array(data); + const noiseSize = Math.floor(Math.random() * 32) + 8; + const noise = crypto.getRandomValues(new Uint8Array(noiseSize)); + const result = new Uint8Array(dataArray.length + noiseSize); + result.set(dataArray, 0); + result.set(noise, dataArray.length); + return result.buffer; + } + randomizeSize(data) { + const dataArray = new Uint8Array(data); + const variation = this.fingerprintMask.sizeVariation; + const targetSize = Math.floor(dataArray.length * variation); + if (targetSize > dataArray.length) { + const padding = crypto.getRandomValues(new Uint8Array(targetSize - dataArray.length)); + const result = new Uint8Array(targetSize); + result.set(dataArray, 0); + result.set(padding, dataArray.length); + return result.buffer; + } else if (targetSize < dataArray.length) { + return dataArray.slice(0, targetSize).buffer; + } + return data; + } + maskPatterns(data) { + const dataArray = new Uint8Array(data); + const result = new Uint8Array(dataArray.length); + for (let i = 0; i < dataArray.length; i++) { + const noiseByte = this.fingerprintMask.noisePattern[i % this.fingerprintMask.noisePattern.length]; + result[i] = dataArray[i] ^ noiseByte; + } + return result.buffer; + } + addRandomHeaders(data) { + const dataArray = new Uint8Array(data); + const headerCount = Math.floor(Math.random() * 3) + 1; + let totalHeaderSize = 0; + for (let i = 0; i < headerCount; i++) { + totalHeaderSize += 4 + Math.floor(Math.random() * 16) + 4; + } + const result = new Uint8Array(totalHeaderSize + dataArray.length); + let offset = 0; + for (let i = 0; i < headerCount; i++) { + const headerName = this.fingerprintMask.headerVariations[Math.floor(Math.random() * this.fingerprintMask.headerVariations.length)]; + const headerData = crypto.getRandomValues(new Uint8Array(Math.floor(Math.random() * 16) + 4)); + const headerView = new DataView(result.buffer, offset); + headerView.setUint32(0, headerData.length + 8, false); + headerView.setUint32(4, this.hashString(headerName), false); + result.set(headerData, offset + 8); + const checksum = this.calculateChecksum(result.slice(offset, offset + 8 + headerData.length)); + const checksumView = new DataView(result.buffer, offset + 8 + headerData.length); + checksumView.setUint32(0, checksum, false); + offset += 8 + headerData.length + 4; + } + result.set(dataArray, offset); + return result.buffer; + } + hashString(str) { + let hash = 0; + for (let i = 0; i < str.length; i++) { + const char = str.charCodeAt(i); + hash = (hash << 5) - hash + char; + hash = hash & hash; + } + return Math.abs(hash); + } + calculateChecksum(data) { + let checksum = 0; + for (let i = 0; i < data.length; i++) { + checksum = checksum + data[i] & 4294967295; + } + return checksum; + } + // ============================================ + // ENHANCED MESSAGE SENDING AND RECEIVING + // ============================================ + async removeSecurityLayers(data) { + try { + const status = this.getSecurityStatus(); + if (this._debugMode) { + this._secureLog("debug", `\u{1F50D} removeSecurityLayers (Stage ${status.stage})`, { + dataType: typeof data, + dataLength: data?.length || data?.byteLength || 0, + activeFeatures: status.activeFeaturesCount + }); + } + if (!data) { + this._secureLog("warn", "\u26A0\uFE0F Received empty data"); + return null; + } + let processedData = data; + if (typeof data === "string") { + try { + const jsonData = JSON.parse(data); + if (jsonData.type === "fake") { + if (this._debugMode) { + this._secureLog("debug", `\u{1F3AD} Fake message filtered out: ${jsonData.pattern} (size: ${jsonData.size})`); + } + return "FAKE_MESSAGE_FILTERED"; + } + if (jsonData.type && ["heartbeat", "verification", "verification_response", "peer_disconnect", "key_rotation_signal", "key_rotation_ready", "security_upgrade"].includes(jsonData.type)) { + if (this._debugMode) { + this._secureLog("debug", "\u{1F527} System message detected, blocking from chat", { type: jsonData.type }); + } + return "SYSTEM_MESSAGE_FILTERED"; + } + if (jsonData.type && ["file_transfer_start", "file_transfer_response", "file_chunk", "chunk_confirmation", "file_transfer_complete", "file_transfer_error"].includes(jsonData.type)) { + if (this._debugMode) { + this._secureLog("debug", "\u{1F4C1} File transfer message detected, blocking from chat", { type: jsonData.type }); + } + return "FILE_MESSAGE_FILTERED"; + } + if (jsonData.type === "message") { + if (this._debugMode) { + this._secureLog("debug", "\u{1F4DD} Regular message detected, extracting text", { data: jsonData.data }); + } + return jsonData.data; + } + if (jsonData.type === "enhanced_message" && jsonData.data) { + if (this._debugMode) { + this._secureLog("debug", "\u{1F510} Enhanced message detected, decrypting..."); + } + if (!this.encryptionKey || !this.macKey || !this.metadataKey) { + this._secureLog("error", "\u274C Missing encryption keys"); + return null; + } + const decryptedResult = await window.EnhancedSecureCryptoUtils.decryptMessage( + jsonData.data, + this.encryptionKey, + this.macKey, + this.metadataKey + ); + if (this._debugMode) { + this._secureLog("debug", "\u2705 Enhanced message decrypted, extracting..."); + this._secureLog("debug", "\u{1F50D} decryptedResult", { + type: typeof decryptedResult, + hasMessage: !!decryptedResult?.message, + messageType: typeof decryptedResult?.message, + messageLength: decryptedResult?.message?.length || 0, + messageSample: decryptedResult?.message?.substring(0, 50) || "no message" + }); + } + try { + const decryptedContent = JSON.parse(decryptedResult.message); + if (decryptedContent.type === "fake" || decryptedContent.isFakeTraffic === true) { + if (this._debugMode) { + this._secureLog("warn", `\u{1F3AD} BLOCKED: Encrypted fake message: ${decryptedContent.pattern || "unknown"}`); + } + return "FAKE_MESSAGE_FILTERED"; + } + } catch (e) { + if (this._debugMode) { + this._secureLog("debug", "\u{1F4DD} Decrypted content is not JSON, treating as plain text message"); + } + } + if (this._debugMode) { + this._secureLog("debug", "\u{1F4E4} Returning decrypted message", { message: decryptedResult.message?.substring(0, 50) }); + } + return decryptedResult.message; + } + if (jsonData.type === "message" && jsonData.data) { + if (this._debugMode) { + this._secureLog("debug", "\u{1F4DD} Regular message detected, extracting data"); + } + return jsonData.data; + } + if (jsonData.type === "message") { + if (this._debugMode) { + this._secureLog("debug", "\u{1F4DD} Regular message detected, returning for display"); + } + return data; + } + if (!jsonData.type || jsonData.type !== "fake" && !["heartbeat", "verification", "verification_response", "peer_disconnect", "key_rotation_signal", "key_rotation_ready", "enhanced_message", "security_upgrade", "file_transfer_start", "file_transfer_response", "file_chunk", "chunk_confirmation", "file_transfer_complete", "file_transfer_error"].includes(jsonData.type)) { + if (this._debugMode) { + this._secureLog("debug", "\u{1F4DD} Regular message detected, returning for display"); + } + return data; + } + } catch (e) { + if (this._debugMode) { + this._secureLog("debug", "\u{1F4C4} Not JSON, processing as raw data"); + } + return data; + } + } + if (this.encryptionKey && typeof processedData === "string" && processedData.length > 50) { + try { + const base64Regex = /^[A-Za-z0-9+/=]+$/; + if (base64Regex.test(processedData.trim())) { + if (this._debugMode) { + this._secureLog("debug", "\u{1F513} Applying standard decryption..."); + } + processedData = await window.EnhancedSecureCryptoUtils.decryptData(processedData, this.encryptionKey); + if (this._debugMode) { + this._secureLog("debug", "\u2705 Standard decryption successful"); + } + if (typeof processedData === "string") { + try { + const legacyContent = JSON.parse(processedData); + if (legacyContent.type === "fake" || legacyContent.isFakeTraffic === true) { + if (this._debugMode) { + this._secureLog("warn", `\u{1F3AD} BLOCKED: Legacy fake message: ${legacyContent.pattern || "unknown"}`); + } + return "FAKE_MESSAGE_FILTERED"; + } + } catch (e) { + } + processedData = new TextEncoder().encode(processedData).buffer; + } + } + } catch (error) { + if (this._debugMode) { + this._secureLog("warn", "\u26A0\uFE0F Standard decryption failed:", { details: error.message }); + } + return data; + } + } + if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey && processedData instanceof ArrayBuffer && processedData.byteLength > 12) { + try { + processedData = await this.removeNestedEncryption(processedData); + if (processedData instanceof ArrayBuffer) { + try { + const textData = new TextDecoder().decode(processedData); + const nestedContent = JSON.parse(textData); + if (nestedContent.type === "fake" || nestedContent.isFakeTraffic === true) { + if (this._debugMode) { + this._secureLog("warn", `\u{1F3AD} BLOCKED: Nested fake message: ${nestedContent.pattern || "unknown"}`); + } + return "FAKE_MESSAGE_FILTERED"; + } + } catch (e) { + } + } + } catch (error) { + if (this._debugMode) { + this._secureLog("warn", "\u26A0\uFE0F Nested decryption failed - skipping this layer:", { details: error.message }); + } + } + } + if (this.securityFeatures.hasPacketReordering && this.reorderingConfig.enabled && processedData instanceof ArrayBuffer) { + try { + const headerSize = this.reorderingConfig.useTimestamps ? 12 : 8; + if (processedData.byteLength > headerSize) { + return await this.processReorderedPacket(processedData); + } + } catch (error) { + if (this._debugMode) { + this._secureLog("warn", "\u26A0\uFE0F Reordering processing failed - using direct processing:", { details: error.message }); + } + } + } + if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) { + try { + processedData = this.removePacketPadding(processedData); + } catch (error) { + if (this._debugMode) { + this._secureLog("warn", "\u26A0\uFE0F Padding removal failed:", { details: error.message }); + } + } + } + if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) { + try { + processedData = this.removeAntiFingerprinting(processedData); + } catch (error) { + if (this._debugMode) { + this._secureLog("warn", "\u26A0\uFE0F Anti-fingerprinting removal failed:", { details: error.message }); + } + } + } + if (processedData instanceof ArrayBuffer) { + processedData = new TextDecoder().decode(processedData); + } + if (typeof processedData === "string") { + try { + const finalContent = JSON.parse(processedData); + if (finalContent.type === "fake" || finalContent.isFakeTraffic === true) { + if (this._debugMode) { + this._secureLog("warn", `\u{1F3AD} BLOCKED: Final check fake message: ${finalContent.pattern || "unknown"}`); + } + return "FAKE_MESSAGE_FILTERED"; + } + } catch (e) { + } + } + return processedData; + } catch (error) { + this._secureLog("error", "\u274C Critical error in removeSecurityLayers:", { errorType: error?.constructor?.name || "Unknown" }); + return data; + } + } + removeAntiFingerprinting(data) { + return data; + } + async applySecurityLayers(data, isFakeMessage = false) { + try { + let processedData = data; + if (isFakeMessage) { + if (this.encryptionKey && typeof processedData === "string") { + processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey); + } + return processedData; + } + if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey && processedData instanceof ArrayBuffer) { + processedData = await this.applyNestedEncryption(processedData); + } + if (this.securityFeatures.hasPacketReordering && this.reorderingConfig?.enabled && processedData instanceof ArrayBuffer) { + processedData = this.applyPacketReordering(processedData); + } + if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) { + processedData = this.applyPacketPadding(processedData); + } + if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) { + processedData = this.applyAntiFingerprinting(processedData); + } + if (this.encryptionKey && typeof processedData === "string") { + processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey); + } + return processedData; + } catch (error) { + this._secureLog("error", "\u274C Error in applySecurityLayers:", { errorType: error?.constructor?.name || "Unknown" }); + return data; + } + } + async sendMessage(data) { + const validation = this._validateInputData(data, "sendMessage"); + if (!validation.isValid) { + const errorMessage = `Input validation failed: ${validation.errors.join(", ")}`; + this._secureLog("error", "\u274C Input validation failed in sendMessage", { + errors: validation.errors, + dataType: typeof data, + dataLength: data?.length || data?.byteLength || 0 + }); + throw new Error(errorMessage); + } + if (!this._checkRateLimit("sendMessage")) { + throw new Error("Rate limit exceeded for message sending"); + } + this._enforceVerificationGate("sendMessage"); + if (!this.dataChannel || this.dataChannel.readyState !== "open") { + throw new Error("Data channel not ready"); + } + try { + this._secureLog("debug", "sendMessage called", { + hasDataChannel: !!this.dataChannel, + dataChannelReady: this.dataChannel?.readyState === "open", + isInitiator: this.isInitiator, + isVerified: this.isVerified, + connectionReady: this.peerConnection?.connectionState === "connected" + }); + this._secureLog("debug", "\u{1F50D} sendMessage DEBUG", { + dataType: typeof validation.sanitizedData, + isString: typeof validation.sanitizedData === "string", + isArrayBuffer: validation.sanitizedData instanceof ArrayBuffer, + dataLength: validation.sanitizedData?.length || validation.sanitizedData?.byteLength || 0 + }); + if (typeof validation.sanitizedData === "string") { + try { + const parsed = JSON.parse(validation.sanitizedData); + if (parsed.type && parsed.type.startsWith("file_")) { + this._secureLog("debug", "\u{1F4C1} File message detected - applying full encryption with AAD", { type: parsed.type }); + const aad = this._createFileMessageAAD(parsed.type, parsed.data); + const encryptedData = await this._encryptFileMessage(validation.sanitizedData, aad); + this.dataChannel.send(encryptedData); + return true; + } + } catch (jsonError) { + } + } + if (typeof validation.sanitizedData === "string") { + if (typeof this._createMessageAAD !== "function") { + throw new Error("_createMessageAAD method is not available. Manager may not be fully initialized."); + } + const aad = this._createMessageAAD("message", { content: validation.sanitizedData }); + return await this.sendSecureMessage({ + type: "message", + data: validation.sanitizedData, + timestamp: Date.now(), + aad + // Include AAD for sequence number validation + }); + } + this._secureLog("debug", "\u{1F510} Applying security layers to non-string data"); + const securedData = await this._applySecurityLayersWithLimitedMutex(validation.sanitizedData, false); + this.dataChannel.send(securedData); + return true; + } catch (error) { + this._secureLog("error", "\u274C Failed to send message", { + error: error.message, + errorType: error.constructor.name + }); + throw error; + } + } + // FIX: New method applying security layers with limited mutex use + async _applySecurityLayersWithLimitedMutex(data, isFakeMessage = false) { + return this._withMutex("cryptoOperation", async (operationId) => { + try { + let processedData = data; + if (isFakeMessage) { + if (this.encryptionKey && typeof processedData === "string") { + processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey); + } + return processedData; + } + if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey && processedData instanceof ArrayBuffer) { + processedData = await this.applyNestedEncryption(processedData); + } + if (this.securityFeatures.hasPacketReordering && this.reorderingConfig?.enabled && processedData instanceof ArrayBuffer) { + processedData = this.applyPacketReordering(processedData); + } + if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) { + processedData = this.applyPacketPadding(processedData); + } + if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) { + processedData = this.applyAntiFingerprinting(processedData); + } + if (this.encryptionKey && typeof processedData === "string") { + processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey); + } + return processedData; + } catch (error) { + this._secureLog("error", "\u274C Error in applySecurityLayers:", { errorType: error?.constructor?.name || "Unknown" }); + return data; + } + }, 3e3); + } + async sendSystemMessage(messageData) { + const isVerificationMessage = messageData.type === "verification_request" || messageData.type === "verification_response" || messageData.type === "verification_required"; + if (!isVerificationMessage) { + this._enforceVerificationGate("sendSystemMessage", false); + } + if (!this.dataChannel || this.dataChannel.readyState !== "open") { + this._secureLog("warn", "\u26A0\uFE0F Cannot send system message - data channel not ready"); + return false; + } + try { + const systemMessage = JSON.stringify({ + type: messageData.type, + data: messageData, + timestamp: Date.now() + }); + this._secureLog("debug", "\u{1F527} Sending system message", { type: messageData.type }); + this.dataChannel.send(systemMessage); + return true; + } catch (error) { + this._secureLog("error", "\u274C Failed to send system message:", { errorType: error?.constructor?.name || "Unknown" }); + return false; + } + } + // FIX 1: Simplified mutex system for message processing + async processMessage(data) { + try { + this._secureLog("debug", "\uFFFD\uFFFD Processing message", { + dataType: typeof data, + isArrayBuffer: data instanceof ArrayBuffer, + hasData: !!(data?.length || data?.byteLength) + }); + if (typeof data === "string") { + try { + const parsed = JSON.parse(data); + const fileMessageTypes2 = [ + "file_transfer_start", + "file_transfer_response", + "file_chunk", + "chunk_confirmation", + "file_transfer_complete", + "file_transfer_error" + ]; + if (parsed.type === "encrypted_file_message") { + this._secureLog("debug", "\u{1F4C1} Encrypted file message detected in processMessage"); + try { + const { decryptedData, aad } = await this._decryptFileMessage(data); + const decryptedParsed = JSON.parse(decryptedData); + this._secureLog("debug", "\u{1F4C1} File message decrypted successfully", { + type: decryptedParsed.type, + aadMessageType: aad.messageType + }); + if (this.fileTransferSystem && typeof this.fileTransferSystem.handleFileMessage === "function") { + await this.fileTransferSystem.handleFileMessage(decryptedParsed); + return; + } + } catch (error) { + this._secureLog("error", "\u274C Failed to decrypt file message", { error: error.message }); + return; + } + } + if (parsed.type && fileMessageTypes2.includes(parsed.type)) { + this._secureLog("warn", "\u26A0\uFE0F Unencrypted file message detected - this should not happen in secure mode", { type: parsed.type }); + this._secureLog("error", "\u274C Dropping unencrypted file message for security", { type: parsed.type }); + return; + } + if (parsed.type === "enhanced_message") { + this._secureLog("debug", "\u{1F510} Enhanced message detected in processMessage"); + try { + const decryptedData = await window.EnhancedSecureCryptoUtils.decryptMessage( + parsed.data, + this.encryptionKey, + this.macKey, + this.metadataKey + ); + const decryptedParsed = JSON.parse(decryptedData.data); + if (decryptedData.metadata && decryptedData.metadata.sequenceNumber !== void 0) { + if (!this._validateIncomingSequenceNumber(decryptedData.metadata.sequenceNumber, "enhanced_message")) { + this._secureLog("warn", "\u26A0\uFE0F Enhanced message sequence number validation failed - possible replay attack", { + received: decryptedData.metadata.sequenceNumber, + expected: this.expectedSequenceNumber + }); + return; + } + } + if (decryptedParsed.type === "message" && this.onMessage && decryptedParsed.data) { + this.deliverMessageToUI(decryptedParsed.data, "received"); + } + return; + } catch (error) { + this._secureLog("error", "\u274C Failed to decrypt enhanced message", { error: error.message }); + return; + } + } + if (parsed.type === "message") { + this._secureLog("debug", "\u{1F4DD} Regular user message detected in processMessage"); + if (this.onMessage && parsed.data) { + this.deliverMessageToUI(parsed.data, "received"); + } + return; + } + if (parsed.type && ["heartbeat", "verification", "verification_response", "verification_confirmed", "verification_both_confirmed", "peer_disconnect", "security_upgrade"].includes(parsed.type)) { + this.handleSystemMessage(parsed); + return; + } + if (parsed.type === "fake") { + this._secureLog("warn", "\u{1F3AD} Fake message blocked in processMessage", { pattern: parsed.pattern }); + return; + } + } catch (jsonError) { + if (this.onMessage) { + this.deliverMessageToUI(data, "received"); + } + return; + } + } + const originalData = await this._processEncryptedDataWithLimitedMutex(data); + if (originalData === "FAKE_MESSAGE_FILTERED" || originalData === "FILE_MESSAGE_FILTERED" || originalData === "SYSTEM_MESSAGE_FILTERED") { + return; + } + if (!originalData) { + this._secureLog("warn", "\u26A0\uFE0F No data returned from removeSecurityLayers"); + return; + } + let messageText; + if (typeof originalData === "string") { + try { + const message = JSON.parse(originalData); + if (message.type && fileMessageTypes.includes(message.type)) { + this._secureLog("debug", "\u{1F4C1} File message detected after decryption", { type: message.type }); + if (this.fileTransferSystem) { + await this.fileTransferSystem.handleFileMessage(message); + } + return; + } + if (message.type && ["heartbeat", "verification", "verification_response", "verification_confirmed", "verification_both_confirmed", "peer_disconnect", "security_upgrade"].includes(message.type)) { + this.handleSystemMessage(message); + return; + } + if (message.type === "fake") { + this._secureLog("warn", `\u{1F3AD} Post-decryption fake message blocked: ${message.pattern}`); + return; + } + if (message.type === "message" && message.data) { + messageText = message.data; + } else { + messageText = originalData; + } + } catch (e) { + messageText = originalData; + } + } else if (originalData instanceof ArrayBuffer) { + messageText = new TextDecoder().decode(originalData); + } else if (originalData && typeof originalData === "object" && originalData.message) { + messageText = originalData.message; + } else { + this._secureLog("warn", "\u26A0\uFE0F Unexpected data type after processing:", { details: typeof originalData }); + return; + } + if (messageText && messageText.trim().startsWith("{")) { + try { + const finalCheck = JSON.parse(messageText); + if (finalCheck.type === "fake") { + this._secureLog("warn", `\u{1F3AD} Final fake message check blocked: ${finalCheck.pattern}`); + return; + } + const blockedTypes = [ + "file_transfer_start", + "file_transfer_response", + "file_chunk", + "chunk_confirmation", + "file_transfer_complete", + "file_transfer_error", + "heartbeat", + "verification", + "verification_response", + "peer_disconnect", + "key_rotation_signal", + "key_rotation_ready", + "security_upgrade" + ]; + if (finalCheck.type && blockedTypes.includes(finalCheck.type)) { + this._secureLog("warn", `\u{1F4C1} Final system/file message check blocked: ${finalCheck.type}`); + return; + } + } catch (e) { + } + } + if (this.onMessage && messageText) { + this._secureLog("debug", "\u{1F4E4} Calling message handler with", { message: messageText.substring(0, 100) }); + this.deliverMessageToUI(messageText, "received"); + } + } catch (error) { + this._secureLog("error", "\u274C Failed to process message:", { errorType: error?.constructor?.name || "Unknown" }); + } + } + // FIX: New method with limited mutex when processing encrypted data + async _processEncryptedDataWithLimitedMutex(data) { + return this._withMutex("cryptoOperation", async (operationId) => { + this._secureLog("debug", "\u{1F510} Processing encrypted data with limited mutex", { + operationId, + dataType: typeof data + }); + try { + const originalData = await this.removeSecurityLayers(data); + return originalData; + } catch (error) { + this._secureLog("error", "\u274C Error processing encrypted data", { + operationId, + errorType: error.constructor.name + }); + return data; + } + }, 2e3); + } + notifySecurityUpdate() { + try { + this._secureLog("debug", "\u{1F512} Notifying about security level update", { + isConnected: this.isConnected(), + isVerified: this.isVerified, + hasKeys: !!(this.encryptionKey && this.macKey && this.metadataKey), + hasLastCalculation: !!this.lastSecurityCalculation + }); + document.dispatchEvent(new CustomEvent("security-level-updated", { + detail: { + timestamp: Date.now(), + manager: "webrtc", + webrtcManager: this, + isConnected: this.isConnected(), + isVerified: this.isVerified, + hasKeys: !!(this.encryptionKey && this.macKey && this.metadataKey), + lastCalculation: this.lastSecurityCalculation + } + })); + setTimeout(() => { + }, 100); + if (this.lastSecurityCalculation) { + document.dispatchEvent(new CustomEvent("real-security-calculated", { + detail: { + securityData: this.lastSecurityCalculation, + webrtcManager: this, + timestamp: Date.now() + } + })); + } + } catch (error) { + this._secureLog("error", "\u274C Error in notifySecurityUpdate", { + error: error.message + }); + } + } + handleSystemMessage(message) { + this._secureLog("debug", "\u{1F527} Handling system message:", { type: message.type }); + switch (message.type) { + case "heartbeat": + this.handleHeartbeat(); + break; + case "verification": + this.handleVerificationRequest(message.data); + break; + case "verification_response": + this.handleVerificationResponse(message.data); + break; + case "sas_code": + this.handleSASCode(message.data); + break; + case "verification_confirmed": + this.handleVerificationConfirmed(message.data); + break; + case "verification_both_confirmed": + this.handleVerificationBothConfirmed(message.data); + break; + case "peer_disconnect": + this.handlePeerDisconnectNotification(message); + break; + case "key_rotation_signal": + this._secureLog("debug", "\u{1F504} Key rotation signal received (ignored for stability)"); + break; + case "key_rotation_ready": + this._secureLog("debug", "\u{1F504} Key rotation ready signal received (ignored for stability)"); + break; + case "security_upgrade": + this._secureLog("debug", "\u{1F512} Security upgrade notification received:", { type: message.type }); + break; + default: + this._secureLog("debug", "\u{1F527} Unknown system message type:", { type: message.type }); + } + } + // ============================================ + // FUNCTION MANAGEMENT METHODS + // ============================================ + // Method to enable Stage 2 functions + enableStage2Security() { + if (this.sessionConstraints?.hasPacketReordering) { + this.securityFeatures.hasPacketReordering = true; + this.reorderingConfig.enabled = true; + } + if (this.sessionConstraints?.hasAntiFingerprinting) { + this.securityFeatures.hasAntiFingerprinting = true; + this.antiFingerprintingConfig.enabled = true; + if (this.currentSecurityLevel === "enhanced") { + this.antiFingerprintingConfig.randomizeSizes = false; + this.antiFingerprintingConfig.maskPatterns = false; + this.antiFingerprintingConfig.useRandomHeaders = false; + } + } + this.notifySecurityUpgrade(2); + setTimeout(() => { + this.calculateAndReportSecurityLevel(); + }, 500); + } + // Method to enable Stage 3 features (traffic obfuscation) + enableStage3Security() { + if (this.currentSecurityLevel !== "maximum") { + this._secureLog("info", "\u{1F512} Stage 3 features only available for premium sessions"); + return; + } + if (this.sessionConstraints?.hasMessageChunking) { + this.securityFeatures.hasMessageChunking = true; + this.chunkingConfig.enabled = true; + } + if (this.sessionConstraints?.hasFakeTraffic) { + this.securityFeatures.hasFakeTraffic = true; + this.fakeTrafficConfig.enabled = true; + this.startFakeTrafficGeneration(); + } + this.notifySecurityUpgrade(3); + setTimeout(() => { + this.calculateAndReportSecurityLevel(); + }, 500); + } + // Method for enabling Stage 4 functions (maximum safety) + enableStage4Security() { + if (this.currentSecurityLevel !== "maximum") { + this._secureLog("info", "\u{1F512} Stage 4 features only available for premium sessions"); + return; + } + if (this.sessionConstraints?.hasDecoyChannels && this.isConnected() && this.isVerified) { + this.securityFeatures.hasDecoyChannels = true; + this.decoyChannelConfig.enabled = true; + try { + this.initializeDecoyChannels(); + } catch (error) { + this._secureLog("warn", "\u26A0\uFE0F Decoy channels initialization failed:", { details: error.message }); + this.securityFeatures.hasDecoyChannels = false; + this.decoyChannelConfig.enabled = false; + } + } + if (this.sessionConstraints?.hasAntiFingerprinting) { + this.antiFingerprintingConfig.randomizeSizes = true; + this.antiFingerprintingConfig.maskPatterns = true; + this.antiFingerprintingConfig.useRandomHeaders = false; + } + this.notifySecurityUpgrade(4); + setTimeout(() => { + this.calculateAndReportSecurityLevel(); + }, 500); + } + forceSecurityUpdate() { + setTimeout(() => { + this.calculateAndReportSecurityLevel(); + this.notifySecurityUpdate(); + }, 100); + } + // Method for getting security status + getSecurityStatus() { + const activeFeatures = Object.entries(this.securityFeatures).filter(([key, value]) => value === true).map(([key]) => key); + const stage = this.currentSecurityLevel === "basic" ? 1 : this.currentSecurityLevel === "enhanced" ? 2 : this.currentSecurityLevel === "maximum" ? 4 : 1; + return { + stage, + sessionType: this.currentSessionType, + securityLevel: this.currentSecurityLevel, + activeFeatures, + totalFeatures: Object.keys(this.securityFeatures).length, + activeFeaturesCount: activeFeatures.length, + activeFeaturesNames: activeFeatures, + sessionConstraints: this.sessionConstraints + }; + } + // Method to notify UI about security update + notifySecurityUpgrade(stage) { + const stageNames = { + 1: "Basic Enhanced", + 2: "Medium Security", + 3: "High Security", + 4: "Maximum Security" + }; + const message = `\u{1F512} Security upgraded to Stage ${stage}: ${stageNames[stage]}`; + if (!this.securityUpgradeNotificationSent || this.lastSecurityUpgradeStage !== stage) { + this.securityUpgradeNotificationSent = true; + this.lastSecurityUpgradeStage = stage; + if (this.onMessage) { + this.deliverMessageToUI(message, "system"); + } + } + if (this.dataChannel && this.dataChannel.readyState === "open") { + try { + const securityNotification = { + type: "security_upgrade", + stage, + stageName: stageNames[stage], + message, + timestamp: Date.now() + }; + this._secureLog("debug", "\u{1F512} Sending security upgrade notification to peer:", { type: securityNotification.type, stage: securityNotification.stage }); + this.dataChannel.send(JSON.stringify(securityNotification)); + } catch (error) { + this._secureLog("warn", "\u26A0\uFE0F Failed to send security upgrade notification to peer:", { details: error.message }); + } + } + const status = this.getSecurityStatus(); + } + async calculateAndReportSecurityLevel() { + try { + if (!window.EnhancedSecureCryptoUtils) { + this._secureLog("warn", "\u26A0\uFE0F EnhancedSecureCryptoUtils not available for security calculation"); + return null; + } + if (!this.isConnected() || !this.isVerified || !this.encryptionKey || !this.macKey) { + this._secureLog("debug", "\u26A0\uFE0F WebRTC not ready for security calculation", { + connected: this.isConnected(), + verified: this.isVerified, + hasEncryptionKey: !!this.encryptionKey, + hasMacKey: !!this.macKey + }); + return null; + } + this._secureLog("debug", "\u{1F50D} Calculating real security level", { + managerState: "ready", + hasAllKeys: !!(this.encryptionKey && this.macKey && this.metadataKey) + }); + const securityData = await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(this); + this._secureLog("info", "\u{1F510} Real security level calculated", { + hasSecurityLevel: !!securityData.level, + scoreRange: securityData.score > 80 ? "high" : securityData.score > 50 ? "medium" : "low", + checksRatio: `${securityData.passedChecks}/${securityData.totalChecks}`, + isRealCalculation: securityData.isRealData + }); + this.lastSecurityCalculation = securityData; + document.dispatchEvent(new CustomEvent("real-security-calculated", { + detail: { + securityData, + webrtcManager: this, + timestamp: Date.now(), + source: "calculateAndReportSecurityLevel" + } + })); + if (securityData.isRealData && this.onMessage) { + if (!this.securityCalculationNotificationSent || this.lastSecurityCalculationLevel !== securityData.level) { + this.securityCalculationNotificationSent = true; + this.lastSecurityCalculationLevel = securityData.level; + const message = `\u{1F512} Security Level: ${securityData.level} (${securityData.score}%) - ${securityData.passedChecks}/${securityData.totalChecks} checks passed`; + this.deliverMessageToUI(message, "system"); + } + } + return securityData; + } catch (error) { + this._secureLog("error", "\u274C Failed to calculate real security level", { + errorType: error.constructor.name + }); + return null; + } + } + // ============================================ + // AUTOMATIC STEP-BY-STEP SWITCHING ON + // ============================================ + // Method for automatic feature enablement with stability check + async autoEnableSecurityFeatures() { + if (this.currentSessionType === "demo") { + this._secureLog("info", "\u{1F512} Demo session - keeping basic security only"); + await this.calculateAndReportSecurityLevel(); + this.notifySecurityUpgrade(1); + return; + } + const checkStability = () => { + const isStable = this.isConnected() && this.isVerified && this.connectionAttempts === 0 && this.messageQueue.length === 0 && this.peerConnection?.connectionState === "connected"; + return isStable; + }; + this._secureLog("info", `\u{1F512} ${this.currentSessionType} session - starting graduated security activation`); + await this.calculateAndReportSecurityLevel(); + this.notifySecurityUpgrade(1); + if (this.currentSecurityLevel === "enhanced" || this.currentSecurityLevel === "maximum") { + setTimeout(async () => { + if (checkStability()) { + console.log("\u2705 Activating Stage 2 for paid session"); + this.enableStage2Security(); + await this.calculateAndReportSecurityLevel(); + if (this.currentSecurityLevel === "maximum") { + setTimeout(async () => { + if (checkStability()) { + console.log("\u2705 Activating Stage 3 for premium session"); + this.enableStage3Security(); + await this.calculateAndReportSecurityLevel(); + setTimeout(async () => { + if (checkStability()) { + console.log("\u2705 Activating Stage 4 for premium session"); + this.enableStage4Security(); + await this.calculateAndReportSecurityLevel(); + } + }, 2e4); + } + }, 15e3); + } + } + }, 1e4); + } + } + // ============================================ + // CONNECTION MANAGEMENT WITH ENHANCED SECURITY + // ============================================ + async establishConnection() { + try { + await this.initializeEnhancedSecurity(); + if (this.fakeTrafficConfig.enabled) { + this.startFakeTrafficGeneration(); + } + if (this.decoyChannelConfig.enabled) { + this.initializeDecoyChannels(); + } + } catch (error) { + this._secureLog("error", "\u274C Failed to establish enhanced connection:", { errorType: error?.constructor?.name || "Unknown" }); + this.onStatusChange("disconnected"); + throw error; + } + } + disconnect() { + try { + console.log("\u{1F50C} Disconnecting WebRTC Manager..."); + if (this.fileTransferSystem) { + console.log("\u{1F9F9} Cleaning up file transfer system during disconnect..."); + this.fileTransferSystem.cleanup(); + this.fileTransferSystem = null; + } + this.stopFakeTrafficGeneration(); + for (const [channelName, timer] of this.decoyTimers.entries()) { + clearTimeout(timer); + } + this.decoyTimers.clear(); + for (const [channelName, channel] of this.decoyChannels.entries()) { + if (channel.readyState === "open") { + channel.close(); + } + } + this.decoyChannels.clear(); + this.packetBuffer.clear(); + this.chunkQueue = []; + this._wipeEphemeralKeys(); + this._hardWipeOldKeys(); + this._clearVerificationStates(); + } catch (error) { + this._secureLog("error", "\u274C Error during enhanced disconnect:", { errorType: error?.constructor?.name || "Unknown" }); + } + } + /** + * Clear all verification states and data + * Called when verification is rejected or connection is terminated + */ + _clearVerificationStates() { + try { + console.log("\u{1F9F9} Clearing verification states..."); + this.localVerificationConfirmed = false; + this.remoteVerificationConfirmed = false; + this.bothVerificationsConfirmed = false; + this.isVerified = false; + this.verificationCode = null; + this.pendingSASCode = null; + this.keyFingerprint = null; + this.expectedDTLSFingerprint = null; + this.connectionId = null; + this.processedMessageIds.clear(); + this.verificationNotificationSent = false; + this.verificationInitiationSent = false; + console.log("\u2705 Verification states cleared successfully"); + } catch (error) { + this._secureLog("error", "\u274C Error clearing verification states:", { errorType: error?.constructor?.name || "Unknown" }); + } + } + // Start periodic cleanup for rate limiting and security + startPeriodicCleanup() { + this._secureLog("info", "\u{1F527} Periodic cleanup moved to unified scheduler"); + } + // Calculate current security level with real verification + async calculateSecurityLevel() { + return await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(this); + } + // PFS: Check if key rotation is needed + shouldRotateKeys() { + if (!this.isConnected() || !this.isVerified) { + return false; + } + const now = Date.now(); + const timeSinceLastRotation = now - this.lastKeyRotation; + return timeSinceLastRotation > this.keyRotationInterval || this.messageCounter % 100 === 0; + } + // PFS: Rotate encryption keys for Perfect Forward Secrecy + async rotateKeys() { + return this._withMutex("keyOperation", async (operationId) => { + this._secureLog("info", "\u{1F504} Starting key rotation with mutex", { + operationId + }); + if (!this.isConnected() || !this.isVerified) { + this._secureLog("warn", "\u26A0\uFE0F Key rotation aborted - connection not ready", { + operationId, + isConnected: this.isConnected(), + isVerified: this.isVerified + }); + return false; + } + if (this._keySystemState.isRotating) { + this._secureLog("warn", "\u26A0\uFE0F Key rotation already in progress", { + operationId + }); + return false; + } + try { + this._keySystemState.isRotating = true; + this._keySystemState.lastOperation = "rotation"; + this._keySystemState.lastOperationTime = Date.now(); + const rotationSignal = { + type: "key_rotation_signal", + newVersion: this.currentKeyVersion + 1, + timestamp: Date.now(), + operationId + }; + if (this.dataChannel && this.dataChannel.readyState === "open") { + this.dataChannel.send(JSON.stringify(rotationSignal)); + } else { + throw new Error("Data channel not ready for key rotation"); + } + this._hardWipeOldKeys(); + return new Promise((resolve) => { + this.pendingRotation = { + newVersion: this.currentKeyVersion + 1, + operationId, + resolve, + timeout: setTimeout(() => { + this._secureLog("error", "\u26A0\uFE0F Key rotation timeout", { + operationId + }); + this._keySystemState.isRotating = false; + this.pendingRotation = null; + resolve(false); + }, 1e4) + // 10 seconds timeout + }; + }); + } catch (error) { + this._secureLog("error", "\u274C Key rotation failed in critical section", { + operationId, + errorType: error.constructor.name + }); + this._keySystemState.isRotating = false; + return false; + } + }, 1e4); + } + // Real PFS - Clean up old keys with hard wipe + cleanupOldKeys() { + const now = Date.now(); + const maxKeyAge = _EnhancedSecureWebRTCManager.LIMITS.MAX_KEY_AGE; + let wipedKeysCount = 0; + for (const [version, keySet] of this.oldKeys.entries()) { + if (now - keySet.timestamp > maxKeyAge) { + if (keySet.encryptionKey) { + this._secureWipeMemory(keySet.encryptionKey, "pfs_cleanup_wipe"); + } + if (keySet.macKey) { + this._secureWipeMemory(keySet.macKey, "pfs_cleanup_wipe"); + } + if (keySet.metadataKey) { + this._secureWipeMemory(keySet.metadataKey, "pfs_cleanup_wipe"); + } + keySet.encryptionKey = null; + keySet.macKey = null; + keySet.metadataKey = null; + keySet.keyFingerprint = null; + this.oldKeys.delete(version); + wipedKeysCount++; + this._secureLog("info", "\u{1F9F9} Old PFS keys hard wiped and cleaned up", { + version, + age: Math.round((now - keySet.timestamp) / 1e3) + "s", + timestamp: Date.now() + }); + } + } + if (wipedKeysCount > 0) { + this._secureLog("info", `\u2705 PFS cleanup completed: ${wipedKeysCount} keys hard wiped`, { + timestamp: Date.now() + }); + } + } + // PFS: Get keys for specific version (for decryption) + getKeysForVersion(version) { + const oldKeySet = this.oldKeys.get(version); + if (oldKeySet && oldKeySet.encryptionKey && oldKeySet.macKey && oldKeySet.metadataKey) { + return { + encryptionKey: oldKeySet.encryptionKey, + macKey: oldKeySet.macKey, + metadataKey: oldKeySet.metadataKey + }; + } + if (version === this.currentKeyVersion) { + if (this.encryptionKey && this.macKey && this.metadataKey) { + return { + encryptionKey: this.encryptionKey, + macKey: this.macKey, + metadataKey: this.metadataKey + }; + } + } + window.EnhancedSecureCryptoUtils.secureLog.log("error", "No valid keys found for version", { + requestedVersion: version, + currentVersion: this.currentKeyVersion, + availableVersions: Array.from(this.oldKeys.keys()) + }); + return null; + } + createPeerConnection() { + const config = { + iceServers: [ + { urls: "stun:stun.l.google.com:19302" }, + { urls: "stun:stun1.l.google.com:19302" }, + { urls: "stun:stun2.l.google.com:19302" }, + { urls: "stun:stun3.l.google.com:19302" }, + { urls: "stun:stun4.l.google.com:19302" } + ], + iceCandidatePoolSize: 10, + bundlePolicy: "balanced" + }; + this.peerConnection = new RTCPeerConnection(config); + this.peerConnection.onconnectionstatechange = () => { + const state = this.peerConnection.connectionState; + console.log("Connection state:", state); + if (state === "connected" && !this.isVerified) { + this.onStatusChange("verifying"); + } else if (state === "connected" && this.isVerified) { + this.onStatusChange("connected"); + } else if (state === "disconnected" || state === "closed") { + if (this.intentionalDisconnect) { + this.onStatusChange("disconnected"); + setTimeout(() => this.disconnect(), 100); + } else { + this.onStatusChange("disconnected"); + this._clearVerificationStates(); + } + } else if (state === "failed") { + this.onStatusChange("disconnected"); + } else { + this.onStatusChange(state); + } + }; + this.peerConnection.ondatachannel = (event) => { + console.log("\u{1F517} Data channel received:", { + channelLabel: event.channel.label, + channelState: event.channel.readyState, + isInitiator: this.isInitiator, + channelId: event.channel.id, + protocol: event.channel.protocol + }); + if (event.channel.label === "securechat") { + console.log("\u{1F517} MAIN DATA CHANNEL RECEIVED (answerer side)"); + this.dataChannel = event.channel; + this.setupDataChannel(event.channel); + } else { + console.log("\u{1F517} ADDITIONAL DATA CHANNEL RECEIVED:", event.channel.label); + if (event.channel.label === "heartbeat") { + this.heartbeatChannel = event.channel; + } + } + }; + } + setupDataChannel(channel) { + console.log("\u{1F517} setupDataChannel called:", { + channelLabel: channel.label, + channelState: channel.readyState, + isInitiator: this.isInitiator, + isVerified: this.isVerified + }); + this.dataChannel = channel; + this.dataChannel.onopen = async () => { + console.log("\u{1F517} Data channel opened:", { + isInitiator: this.isInitiator, + isVerified: this.isVerified, + dataChannelState: this.dataChannel.readyState, + dataChannelLabel: this.dataChannel.label + }); + try { + if (this.dataChannel && typeof this.dataChannel.bufferedAmountLowThreshold === "number") { + this.dataChannel.bufferedAmountLowThreshold = 1024 * 1024; + } + } catch (e) { + } + try { + await this.establishConnection(); + this.initializeFileTransfer(); + } catch (error) { + this._secureLog("error", "\u274C Error in establishConnection:", { errorType: error?.constructor?.name || "Unknown" }); + } + if (this.pendingSASCode && this.dataChannel && this.dataChannel.readyState === "open") { + try { + const sasPayload = { + type: "sas_code", + data: { + code: this.pendingSASCode, + timestamp: Date.now(), + verificationMethod: "SAS", + securityLevel: "MITM_PROTECTION_REQUIRED" + } + }; + console.log("\u{1F4E4} Sending pending SAS code to Answer side:", this.pendingSASCode); + this.dataChannel.send(JSON.stringify(sasPayload)); + this.pendingSASCode = null; + } catch (error) { + console.error("Failed to send pending SAS code to Answer side:", error); + } + } else if (this.pendingSASCode) { + console.log("\u26A0\uFE0F Cannot send SAS code - dataChannel not ready:", { + hasDataChannel: !!this.dataChannel, + readyState: this.dataChannel?.readyState, + pendingSASCode: this.pendingSASCode + }); + } + if (this.isVerified) { + this.onStatusChange("connected"); + this.processMessageQueue(); + setTimeout(async () => { + await this.calculateAndReportSecurityLevel(); + this.autoEnableSecurityFeatures(); + this.notifySecurityUpdate(); + }, 500); + } else { + this.onStatusChange("verifying"); + this.initiateVerification(); + } + this.startHeartbeat(); + }; + this.dataChannel.onclose = () => { + if (!this.intentionalDisconnect) { + this.onStatusChange("disconnected"); + this._clearVerificationStates(); + if (!this.connectionClosedNotificationSent) { + this.connectionClosedNotificationSent = true; + this.deliverMessageToUI("\u{1F50C} Enhanced secure connection closed. Check connection status.", "system"); + } + } else { + this.onStatusChange("disconnected"); + this._clearVerificationStates(); + if (!this.connectionClosedNotificationSent) { + this.connectionClosedNotificationSent = true; + this.deliverMessageToUI("\u{1F50C} Enhanced secure connection closed", "system"); + } + } + this._wipeEphemeralKeys(); + this.stopHeartbeat(); + this.isVerified = false; + }; + this.dataChannel.onmessage = async (event) => { + try { + console.log("\u{1F4E8} Raw message received:", { + dataType: typeof event.data, + dataLength: event.data?.length || event.data?.byteLength || 0, + isString: typeof event.data === "string" + }); + if (typeof event.data === "string") { + try { + const parsed = JSON.parse(event.data); + console.log("\u{1F4E8} Parsed message:", { + type: parsed.type, + hasData: !!parsed.data, + timestamp: parsed.timestamp + }); + const fileMessageTypes2 = [ + "file_transfer_start", + "file_transfer_response", + "file_chunk", + "chunk_confirmation", + "file_transfer_complete", + "file_transfer_error" + ]; + if (parsed.type && fileMessageTypes2.includes(parsed.type)) { + console.log("\u{1F4C1} File message intercepted at WebRTC level:", parsed.type); + if (!this.fileTransferSystem) { + try { + if (this.isVerified && this.dataChannel && this.dataChannel.readyState === "open") { + this.initializeFileTransfer(); + let attempts2 = 0; + const maxAttempts = 30; + while (!this.fileTransferSystem && attempts2 < maxAttempts) { + await new Promise((resolve) => setTimeout(resolve, 100)); + attempts2++; + } + } + } catch (initError) { + this._secureLog("error", "\u274C Failed to initialize file transfer system for receiver:", { errorType: initError?.constructor?.name || "Unknown" }); + } + } + if (this.fileTransferSystem) { + console.log("\u{1F4C1} Forwarding to local file transfer system:", parsed.type); + await this.fileTransferSystem.handleFileMessage(parsed); + return; + } + this._secureLog("warn", "\u26A0\uFE0F File transfer system not ready, attempting lazy init..."); + try { + await this._ensureFileTransferReady(); + if (this.fileTransferSystem) { + await this.fileTransferSystem.handleFileMessage(parsed); + return; + } + } catch (e) { + this._secureLog("error", "\u274C Lazy init of file transfer failed:", { errorType: e?.message || e?.constructor?.name || "Unknown" }); + } + this._secureLog("error", "\u274C No file transfer system available for:", { errorType: parsed.type?.constructor?.name || "Unknown" }); + return; + } + if (parsed.type && ["heartbeat", "verification", "verification_response", "verification_confirmed", "verification_both_confirmed", "sas_code", "peer_disconnect", "security_upgrade"].includes(parsed.type)) { + console.log("\u{1F527} System message detected:", parsed.type); + this.handleSystemMessage(parsed); + return; + } + if (parsed.type === "message" && parsed.data) { + console.log("\u{1F4DD} User message detected:", parsed.data.substring(0, 50)); + if (this.onMessage) { + this.deliverMessageToUI(parsed.data, "received"); + } + return; + } + if (parsed.type === "enhanced_message" && parsed.data) { + console.log("\u{1F510} Enhanced message detected, processing..."); + await this._processEnhancedMessageWithoutMutex(parsed); + return; + } + if (parsed.type === "fake") { + console.log("\u{1F3AD} Fake message blocked:", parsed.pattern); + return; + } + console.log("\u2753 Unknown message type:", parsed.type); + } catch (jsonError) { + console.log("\u{1F4C4} Non-JSON message detected, treating as text"); + if (this.onMessage) { + this.deliverMessageToUI(event.data, "received"); + } + return; + } + } else if (event.data instanceof ArrayBuffer) { + console.log("\u{1F522} Binary data received, processing..."); + await this._processBinaryDataWithoutMutex(event.data); + } else { + console.log("\u2753 Unknown data type:", typeof event.data); + } + } catch (error) { + this._secureLog("error", "\u274C Failed to process message in onmessage:", { errorType: error?.constructor?.name || "Unknown" }); + } + }; + } + // FIX 4: New method for processing binary data WITHOUT mutex + async _processBinaryDataWithoutMutex(data) { + try { + console.log("\u{1F522} Processing binary data without mutex..."); + let processedData = data; + if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey && processedData instanceof ArrayBuffer && processedData.byteLength > 12) { + try { + processedData = await this.removeNestedEncryption(processedData); + } catch (error) { + this._secureLog("warn", "\u26A0\uFE0F Nested decryption failed, continuing with original data"); + } + } + if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) { + try { + processedData = this.removePacketPadding(processedData); + } catch (error) { + this._secureLog("warn", "\u26A0\uFE0F Packet padding removal failed, continuing with original data"); + } + } + if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) { + try { + processedData = this.removeAntiFingerprinting(processedData); + } catch (error) { + this._secureLog("warn", "\u26A0\uFE0F Anti-fingerprinting removal failed, continuing with original data"); + } + } + if (processedData instanceof ArrayBuffer) { + const textData = new TextDecoder().decode(processedData); + try { + const content = JSON.parse(textData); + if (content.type === "fake" || content.isFakeTraffic === true) { + console.log(`\u{1F3AD} BLOCKED: Binary fake message: ${content.pattern || "unknown"}`); + return; + } + } catch (e) { + } + if (this.onMessage) { + this.deliverMessageToUI(textData, "received"); + } + } + } catch (error) { + this._secureLog("error", "\u274C Error processing binary data:", { errorType: error?.constructor?.name || "Unknown" }); + } + } + // FIX 3: New method for processing enhanced messages WITHOUT mutex + async _processEnhancedMessageWithoutMutex(parsedMessage) { + try { + console.log("\u{1F510} Processing enhanced message without mutex..."); + if (!this.encryptionKey || !this.macKey || !this.metadataKey) { + this._secureLog("error", "\u274C Missing encryption keys for enhanced message"); + return; + } + const decryptedResult = await window.EnhancedSecureCryptoUtils.decryptMessage( + parsedMessage.data, + this.encryptionKey, + this.macKey, + this.metadataKey + ); + if (decryptedResult && decryptedResult.message) { + console.log("\u2705 Enhanced message decrypted successfully"); + try { + const decryptedContent = JSON.parse(decryptedResult.message); + if (decryptedContent.type === "fake" || decryptedContent.isFakeTraffic === true) { + console.log(`\uFFFD\uFFFD BLOCKED: Encrypted fake message: ${decryptedContent.pattern || "unknown"}`); + return; + } + if (decryptedContent && decryptedContent.type === "message" && typeof decryptedContent.data === "string") { + if (this.onMessage) { + this.deliverMessageToUI(decryptedContent.data, "received"); + } + return; + } + } catch (e) { + } + if (this.onMessage) { + this.deliverMessageToUI(decryptedResult.message, "received"); + } + } else { + this._secureLog("warn", "\u26A0\uFE0F No message content in decrypted result"); + } + } catch (error) { + this._secureLog("error", "\u274C Error processing enhanced message:", { errorType: error?.constructor?.name || "Unknown" }); + } + } + /** + * Creates a unique ID for an operation + */ + _generateOperationId() { + return `op_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + } + /** + * Atomic mutex acquisition with enhanced race condition protection + */ + async _acquireMutex(mutexName, operationId, timeout = 5e3) { + const mutexPropertyName = `_${mutexName}Mutex`; + const mutex = this[mutexPropertyName]; + if (!mutex) { + this._secureLog("error", `\u274C Unknown mutex: ${mutexName}`, { + mutexPropertyName, + availableMutexes: this._getAvailableMutexes(), + operationId + }); + throw new Error(`Unknown mutex: ${mutexName}. Available: ${this._getAvailableMutexes().join(", ")}`); + } + if (!operationId || typeof operationId !== "string") { + throw new Error("Invalid operation ID for mutex acquisition"); + } + return new Promise((resolve, reject) => { + const attemptLock = () => { + if (mutex.lockId === operationId) { + this._secureLog("warn", `\u26A0\uFE0F Mutex '${mutexName}' already locked by same operation`, { + operationId + }); + resolve(); + return; + } + if (!mutex.locked) { + mutex.locked = true; + mutex.lockId = operationId; + mutex.lockTime = Date.now(); + this._secureLog("debug", `\u{1F512} Mutex '${mutexName}' acquired atomically`, { + operationId, + lockTime: mutex.lockTime + }); + mutex.lockTimeout = setTimeout(() => { + this._handleMutexTimeout(mutexName, operationId, timeout); + }, timeout); + resolve(); + } else { + const queueItem = { + resolve, + reject, + operationId, + timestamp: Date.now(), + timeout: setTimeout(() => { + const index = mutex.queue.findIndex((item) => item.operationId === operationId); + if (index !== -1) { + mutex.queue.splice(index, 1); + reject(new Error(`Mutex acquisition timeout for '${mutexName}'`)); + } + }, timeout) + }; + mutex.queue.push(queueItem); + this._secureLog("debug", `\u23F3 Operation queued for mutex '${mutexName}'`, { + operationId, + queueLength: mutex.queue.length, + currentLockId: mutex.lockId + }); + } + }; + attemptLock(); + }); + } + /** + * Enhanced mutex release with strict validation and error handling + */ + _releaseMutex(mutexName, operationId) { + if (!mutexName || typeof mutexName !== "string") { + throw new Error("Invalid mutex name provided for release"); + } + if (!operationId || typeof operationId !== "string") { + throw new Error("Invalid operation ID provided for mutex release"); + } + const mutexPropertyName = `_${mutexName}Mutex`; + const mutex = this[mutexPropertyName]; + if (!mutex) { + this._secureLog("error", `\u274C Unknown mutex for release: ${mutexName}`, { + mutexPropertyName, + availableMutexes: this._getAvailableMutexes(), + operationId + }); + throw new Error(`Unknown mutex for release: ${mutexName}`); + } + if (mutex.lockId !== operationId) { + this._secureLog("error", `\u274C CRITICAL: Invalid mutex release attempt - potential race condition`, { + mutexName, + expectedLockId: mutex.lockId, + providedOperationId: operationId, + mutexState: { + locked: mutex.locked, + lockTime: mutex.lockTime, + queueLength: mutex.queue.length + } + }); + throw new Error(`Invalid mutex release attempt for '${mutexName}': expected '${mutex.lockId}', got '${operationId}'`); + } + if (!mutex.locked) { + this._secureLog("error", `\u274C CRITICAL: Attempting to release unlocked mutex`, { + mutexName, + operationId, + mutexState: { + locked: mutex.locked, + lockId: mutex.lockId, + lockTime: mutex.lockTime + } + }); + throw new Error(`Attempting to release unlocked mutex: ${mutexName}`); + } + try { + if (mutex.lockTimeout) { + clearTimeout(mutex.lockTimeout); + mutex.lockTimeout = null; + } + const lockDuration = mutex.lockTime ? Date.now() - mutex.lockTime : 0; + mutex.locked = false; + mutex.lockId = null; + mutex.lockTime = null; + this._secureLog("debug", `\u{1F513} Mutex released successfully: ${mutexName}`, { + operationId, + lockDuration, + queueLength: mutex.queue.length + }); + this._processNextInQueue(mutexName); + } catch (error) { + this._secureLog("error", `\u274C Error during mutex release queue processing`, { + mutexName, + operationId, + errorType: error.constructor.name, + errorMessage: error.message + }); + mutex.locked = false; + mutex.lockId = null; + mutex.lockTime = null; + mutex.lockTimeout = null; + throw error; + } + } + /** + * Enhanced queue processing with comprehensive error handling + */ + _processNextInQueue(mutexName) { + const mutex = this[`_${mutexName}Mutex`]; + if (!mutex) { + this._secureLog("error", `\u274C Mutex not found for queue processing: ${mutexName}`); + return; + } + if (mutex.queue.length === 0) { + return; + } + if (mutex.locked) { + this._secureLog("warn", `\u26A0\uFE0F Mutex '${mutexName}' is still locked, skipping queue processing`, { + lockId: mutex.lockId, + queueLength: mutex.queue.length + }); + return; + } + const nextItem = mutex.queue.shift(); + if (!nextItem) { + this._secureLog("warn", `\u26A0\uFE0F Empty queue item for mutex '${mutexName}'`); + return; + } + if (!nextItem.operationId || !nextItem.resolve || !nextItem.reject) { + this._secureLog("error", `\u274C Invalid queue item structure for mutex '${mutexName}'`, { + hasOperationId: !!nextItem.operationId, + hasResolve: !!nextItem.resolve, + hasReject: !!nextItem.reject + }); + return; + } + try { + if (nextItem.timeout) { + clearTimeout(nextItem.timeout); + } + this._secureLog("debug", `\u{1F504} Processing next operation in queue for mutex '${mutexName}'`, { + operationId: nextItem.operationId, + queueRemaining: mutex.queue.length, + timestamp: Date.now() + }); + setTimeout(async () => { + try { + await this._acquireMutex(mutexName, nextItem.operationId, 5e3); + this._secureLog("debug", `\u2705 Queued operation acquired mutex '${mutexName}'`, { + operationId: nextItem.operationId, + acquisitionTime: Date.now() + }); + nextItem.resolve(); + } catch (error) { + this._secureLog("error", `\u274C Queued operation failed to acquire mutex '${mutexName}'`, { + operationId: nextItem.operationId, + errorType: error.constructor.name, + errorMessage: error.message, + timestamp: Date.now() + }); + nextItem.reject(new Error(`Queue processing failed for '${mutexName}': ${error.message}`)); + setTimeout(() => { + this._processNextInQueue(mutexName); + }, 50); + } + }, 10); + } catch (error) { + this._secureLog("error", `\u274C Critical error during queue processing for mutex '${mutexName}'`, { + operationId: nextItem.operationId, + errorType: error.constructor.name, + errorMessage: error.message + }); + try { + nextItem.reject(new Error(`Queue processing critical error: ${error.message}`)); + } catch (rejectError) { + this._secureLog("error", `\u274C Failed to reject queue item`, { + originalError: error.message, + rejectError: rejectError.message + }); + } + setTimeout(() => { + this._processNextInQueue(mutexName); + }, 100); + } + } + _getAvailableMutexes() { + const mutexes = []; + const propertyNames = Object.getOwnPropertyNames(this); + for (const prop of propertyNames) { + if (prop.endsWith("Mutex") && prop.startsWith("_")) { + const mutexName = prop.slice(1, -5); + mutexes.push(mutexName); + } + } + return mutexes; + } + /** + * Enhanced mutex execution with atomic operations + */ + async _withMutex(mutexName, operation, timeout = 5e3) { + const operationId = this._generateOperationId(); + if (!this._validateMutexSystem()) { + this._secureLog("error", "\u274C Mutex system not properly initialized", { + operationId, + mutexName + }); + throw new Error("Mutex system not properly initialized. Call _initializeMutexSystem() first."); + } + const mutex = this[`_${mutexName}Mutex`]; + if (!mutex) { + throw new Error(`Mutex '${mutexName}' not found`); + } + let mutexAcquired = false; + try { + await this._acquireMutex(mutexName, operationId, timeout); + mutexAcquired = true; + const counterKey = `${mutexName}Operations`; + if (this._operationCounters && this._operationCounters[counterKey] !== void 0) { + this._operationCounters[counterKey]++; + } + const result = await operation(operationId); + if (result === void 0 && operation.name !== "cleanup") { + this._secureLog("warn", "\u26A0\uFE0F Mutex operation returned undefined result", { + operationId, + mutexName, + operationName: operation.name + }); + } + return result; + } catch (error) { + this._secureLog("error", "\u274C Error in mutex operation", { + operationId, + mutexName, + errorType: error.constructor.name, + errorMessage: error.message, + mutexAcquired, + mutexState: mutex ? { + locked: mutex.locked, + lockId: mutex.lockId, + queueLength: mutex.queue.length + } : "null" + }); + if (mutexName === "keyOperation") { + this._handleKeyOperationError(error, operationId); + } + if (error.message.includes("timeout") || error.message.includes("race condition")) { + this._emergencyUnlockAllMutexes("errorHandler"); + } + throw error; + } finally { + if (mutexAcquired) { + try { + await this._releaseMutex(mutexName, operationId); + if (mutex.locked && mutex.lockId === operationId) { + this._secureLog("error", "\u274C Mutex release verification failed", { + operationId, + mutexName + }); + mutex.locked = false; + mutex.lockId = null; + mutex.lockTimeout = null; + } + } catch (releaseError) { + this._secureLog("error", "\u274C Error releasing mutex in finally block", { + operationId, + mutexName, + releaseErrorType: releaseError.constructor.name, + releaseErrorMessage: releaseError.message + }); + mutex.locked = false; + mutex.lockId = null; + mutex.lockTimeout = null; + } + } + } + } + _validateMutexSystem() { + const requiredMutexes = ["keyOperation", "cryptoOperation", "connectionOperation"]; + for (const mutexName of requiredMutexes) { + const mutexPropertyName = `_${mutexName}Mutex`; + const mutex = this[mutexPropertyName]; + if (!mutex || typeof mutex !== "object") { + this._secureLog("error", `\u274C Missing or invalid mutex: ${mutexName}`, { + mutexPropertyName, + mutexType: typeof mutex + }); + return false; + } + const requiredProps = ["locked", "queue", "lockId", "lockTimeout"]; + for (const prop of requiredProps) { + if (!(prop in mutex)) { + this._secureLog("error", `\u274C Mutex ${mutexName} missing property: ${prop}`); + return false; + } + } + } + return true; + } + /** + * Enhanced emergency recovery of the mutex system + */ + _emergencyRecoverMutexSystem() { + this._secureLog("warn", "\u{1F6A8} Emergency mutex system recovery initiated"); + try { + this._emergencyUnlockAllMutexes("emergencyRecovery"); + this._initializeMutexSystem(); + if (!this._validateMutexSystem()) { + throw new Error("Mutex system validation failed after recovery"); + } + this._secureLog("info", "\u2705 Mutex system recovered successfully with validation"); + return true; + } catch (error) { + this._secureLog("error", "\u274C Failed to recover mutex system", { + errorType: error.constructor.name, + errorMessage: error.message + }); + try { + this._initializeMutexSystem(); + this._secureLog("warn", "\u26A0\uFE0F Forced mutex system re-initialization completed"); + return true; + } catch (reinitError) { + this._secureLog("error", "\u274C CRITICAL: Forced re-initialization also failed", { + originalError: error.message, + reinitError: reinitError.message + }); + return false; + } + } + } + /** + * Atomic key generation with race condition protection + */ + async _generateEncryptionKeys() { + return this._withMutex("keyOperation", async (operationId) => { + this._secureLog("info", "\u{1F511} Generating encryption keys with atomic mutex", { + operationId + }); + const currentState = this._keySystemState; + if (currentState.isInitializing) { + this._secureLog("warn", "\u26A0\uFE0F Key generation already in progress, waiting for completion", { + operationId, + lastOperation: currentState.lastOperation, + lastOperationTime: currentState.lastOperationTime + }); + let waitAttempts = 0; + const maxWaitAttempts = 50; + while (currentState.isInitializing && waitAttempts < maxWaitAttempts) { + await new Promise((resolve) => setTimeout(resolve, 100)); + waitAttempts++; + } + if (currentState.isInitializing) { + throw new Error("Key generation timeout - operation still in progress after 5 seconds"); + } + } + try { + currentState.isInitializing = true; + currentState.lastOperation = "generation"; + currentState.lastOperationTime = Date.now(); + currentState.operationId = operationId; + this._secureLog("debug", "\u{1F512} Atomic key generation state set", { + operationId, + timestamp: currentState.lastOperationTime + }); + let ecdhKeyPair = null; + let ecdsaKeyPair = null; + try { + ecdhKeyPair = await this._generateEphemeralECDHKeys(); + if (!ecdhKeyPair || !ecdhKeyPair.privateKey || !ecdhKeyPair.publicKey) { + throw new Error("Ephemeral ECDH key pair validation failed"); + } + if (!this._validateKeyPairConstantTime(ecdhKeyPair)) { + throw new Error("Ephemeral ECDH keys are not valid CryptoKey instances"); + } + this._secureLog("debug", "\u2705 Ephemeral ECDH keys generated and validated for PFS", { + operationId, + privateKeyType: ecdhKeyPair.privateKey.algorithm?.name, + publicKeyType: ecdhKeyPair.publicKey.algorithm?.name, + isEphemeral: true + }); + } catch (ecdhError) { + this._secureLog("error", "\u274C Ephemeral ECDH key generation failed", { + operationId, + errorType: ecdhError.constructor.name + }); + this._throwSecureError(ecdhError, "ephemeral_ecdh_key_generation"); + } + try { + ecdsaKeyPair = await window.EnhancedSecureCryptoUtils.generateECDSAKeyPair(); + if (!ecdsaKeyPair || !ecdsaKeyPair.privateKey || !ecdsaKeyPair.publicKey) { + throw new Error("ECDSA key pair validation failed"); + } + if (!this._validateKeyPairConstantTime(ecdsaKeyPair)) { + throw new Error("ECDSA keys are not valid CryptoKey instances"); + } + this._secureLog("debug", "\u2705 ECDSA keys generated and validated", { + operationId, + privateKeyType: ecdsaKeyPair.privateKey.algorithm?.name, + publicKeyType: ecdsaKeyPair.publicKey.algorithm?.name + }); + } catch (ecdsaError) { + this._secureLog("error", "\u274C ECDSA key generation failed", { + operationId, + errorType: ecdsaError.constructor.name + }); + this._throwSecureError(ecdsaError, "ecdsa_key_generation"); + } + if (!ecdhKeyPair || !ecdsaKeyPair) { + throw new Error("One or both key pairs failed to generate"); + } + this._enableSecurityFeaturesAfterKeyGeneration(ecdhKeyPair, ecdsaKeyPair); + this._secureLog("info", "\u2705 Encryption keys generated successfully with atomic protection", { + operationId, + hasECDHKeys: !!(ecdhKeyPair?.privateKey && ecdhKeyPair?.publicKey), + hasECDSAKeys: !!(ecdsaKeyPair?.privateKey && ecdsaKeyPair?.publicKey), + generationTime: Date.now() - currentState.lastOperationTime + }); + return { ecdhKeyPair, ecdsaKeyPair }; + } catch (error) { + this._secureLog("error", "\u274C Key generation failed, resetting state", { + operationId, + errorType: error.constructor.name + }); + throw error; + } finally { + currentState.isInitializing = false; + currentState.operationId = null; + this._secureLog("debug", "\u{1F513} Key generation state reset", { + operationId + }); + } + }); + } + /** + * Enable security features after successful key generation + */ + _enableSecurityFeaturesAfterKeyGeneration(ecdhKeyPair, ecdsaKeyPair) { + try { + if (ecdhKeyPair && ecdhKeyPair.privateKey && ecdhKeyPair.publicKey) { + this.securityFeatures.hasEncryption = true; + this.securityFeatures.hasECDH = true; + this._secureLog("info", "\u{1F512} ECDH encryption features enabled"); + } + if (ecdsaKeyPair && ecdsaKeyPair.privateKey && ecdsaKeyPair.publicKey) { + this.securityFeatures.hasECDSA = true; + this._secureLog("info", "\u{1F512} ECDSA signature features enabled"); + } + if (this.securityFeatures.hasEncryption) { + this.securityFeatures.hasMetadataProtection = true; + this.securityFeatures.hasEnhancedReplayProtection = true; + this.securityFeatures.hasNonExtractableKeys = true; + this._secureLog("info", "\u{1F512} Additional encryption-dependent features enabled"); + } + if (ecdhKeyPair && this.ephemeralKeyPairs.size > 0) { + this.securityFeatures.hasPFS = true; + this._secureLog("info", "\u{1F512} Perfect Forward Secrecy enabled with ephemeral keys"); + } + this._secureLog("info", "\u{1F512} Security features updated after key generation", { + hasEncryption: this.securityFeatures.hasEncryption, + hasECDH: this.securityFeatures.hasECDH, + hasECDSA: this.securityFeatures.hasECDSA, + hasMetadataProtection: this.securityFeatures.hasMetadataProtection, + hasEnhancedReplayProtection: this.securityFeatures.hasEnhancedReplayProtection, + hasNonExtractableKeys: this.securityFeatures.hasNonExtractableKeys, + hasPFS: this.securityFeatures.hasPFS + }); + } catch (error) { + this._secureLog("error", "\u274C Failed to enable security features after key generation", { + errorType: error.constructor.name, + errorMessage: error.message + }); + } + } + /** + * Enhanced emergency mutex unlocking with authorization and validation + */ + _emergencyUnlockAllMutexes(callerContext = "unknown") { + const authorizedCallers = [ + "keyOperation", + "cryptoOperation", + "connectionOperation", + "emergencyRecovery", + "systemShutdown", + "errorHandler" + ]; + if (!authorizedCallers.includes(callerContext)) { + this._secureLog("error", `\u{1F6A8} UNAUTHORIZED emergency mutex unlock attempt`, { + callerContext, + authorizedCallers, + timestamp: Date.now() + }); + throw new Error(`Unauthorized emergency mutex unlock attempt by: ${callerContext}`); + } + const mutexes = ["keyOperation", "cryptoOperation", "connectionOperation"]; + this._secureLog("error", "\u{1F6A8} EMERGENCY: Unlocking all mutexes with authorization and state cleanup", { + callerContext, + timestamp: Date.now() + }); + let unlockedCount = 0; + let errorCount = 0; + mutexes.forEach((mutexName) => { + const mutex = this[`_${mutexName}Mutex`]; + if (mutex) { + try { + if (mutex.lockTimeout) { + clearTimeout(mutex.lockTimeout); + } + const previousState = { + locked: mutex.locked, + lockId: mutex.lockId, + lockTime: mutex.lockTime, + queueLength: mutex.queue.length + }; + mutex.locked = false; + mutex.lockId = null; + mutex.lockTimeout = null; + mutex.lockTime = null; + let queueRejectCount = 0; + mutex.queue.forEach((item) => { + try { + if (item.reject && typeof item.reject === "function") { + item.reject(new Error(`Emergency mutex unlock for ${mutexName} by ${callerContext}`)); + queueRejectCount++; + } + } catch (rejectError) { + this._secureLog("warn", `\u26A0\uFE0F Failed to reject queue item during emergency unlock`, { + mutexName, + errorType: rejectError.constructor.name + }); + } + }); + mutex.queue = []; + unlockedCount++; + this._secureLog("debug", `\u{1F513} Emergency unlocked mutex: ${mutexName}`, { + previousState, + queueRejectCount, + callerContext + }); + } catch (error) { + errorCount++; + this._secureLog("error", `\u274C Error during emergency unlock of mutex: ${mutexName}`, { + errorType: error.constructor.name, + errorMessage: error.message, + callerContext + }); + } + } + }); + if (this._keySystemState) { + try { + const previousKeyState = { ...this._keySystemState }; + this._keySystemState.isInitializing = false; + this._keySystemState.isRotating = false; + this._keySystemState.isDestroying = false; + this._keySystemState.operationId = null; + this._keySystemState.concurrentOperations = 0; + this._secureLog("debug", `\u{1F513} Emergency reset key system state`, { + previousState: previousKeyState, + callerContext + }); + } catch (error) { + this._secureLog("error", `\u274C Error resetting key system state during emergency unlock`, { + errorType: error.constructor.name, + errorMessage: error.message, + callerContext + }); + } + } + this._secureLog("info", `\u{1F6A8} Emergency mutex unlock completed`, { + callerContext, + unlockedCount, + errorCount, + totalMutexes: mutexes.length, + timestamp: Date.now() + }); + setTimeout(() => { + this._validateMutexSystemAfterEmergencyUnlock(); + }, 100); + } + /** + * Handle key operation errors with recovery mechanisms + */ + _handleKeyOperationError(error, operationId) { + this._secureLog("error", "\u{1F6A8} Key operation error detected, initiating recovery", { + operationId, + errorType: error.constructor.name, + errorMessage: error.message + }); + if (this._keySystemState) { + this._keySystemState.isInitializing = false; + this._keySystemState.isRotating = false; + this._keySystemState.isDestroying = false; + this._keySystemState.operationId = null; + } + this.ecdhKeyPair = null; + this.ecdsaKeyPair = null; + this.encryptionKey = null; + this.macKey = null; + this.metadataKey = null; + if (error.message.includes("timeout") || error.message.includes("race condition")) { + this._secureLog("warn", "\u26A0\uFE0F Race condition or timeout detected, triggering emergency recovery"); + this._emergencyRecoverMutexSystem(); + } + } + /** + * Generate cryptographically secure IV with reuse prevention + */ + _generateSecureIV(ivSize = 12, context = "general") { + if (this._ivTrackingSystem.emergencyMode) { + this._secureLog("error", "\u{1F6A8} CRITICAL: IV generation blocked - emergency mode active due to IV reuse"); + throw new Error("IV generation blocked - emergency mode active"); + } + let attempts2 = 0; + const maxAttempts = 100; + while (attempts2 < maxAttempts) { + attempts2++; + const iv = crypto.getRandomValues(new Uint8Array(ivSize)); + const ivString = Array.from(iv).map((b) => b.toString(16).padStart(2, "0")).join(""); + if (this._ivTrackingSystem.usedIVs.has(ivString)) { + this._ivTrackingSystem.collisionCount++; + this._secureLog("error", `\u{1F6A8} CRITICAL: IV reuse detected!`, { + context, + attempt: attempts2, + collisionCount: this._ivTrackingSystem.collisionCount, + ivString: ivString.substring(0, 16) + "..." + // Log partial IV for debugging + }); + if (this._ivTrackingSystem.collisionCount > 5) { + this._ivTrackingSystem.emergencyMode = true; + this._secureLog("error", "\u{1F6A8} CRITICAL: Emergency mode activated due to excessive IV reuse"); + throw new Error("Emergency mode: Excessive IV reuse detected"); + } + continue; + } + if (!this._validateIVEntropy(iv)) { + this._ivTrackingSystem.entropyValidation.entropyFailures++; + this._secureLog("warn", `\u26A0\uFE0F Low entropy IV detected`, { + context, + attempt: attempts2, + entropyFailures: this._ivTrackingSystem.entropyValidation.entropyFailures + }); + if (this._ivTrackingSystem.entropyValidation.entropyFailures > 10) { + this._ivTrackingSystem.emergencyMode = true; + this._secureLog("error", "\u{1F6A8} CRITICAL: Emergency mode activated due to low entropy IVs"); + throw new Error("Emergency mode: Low entropy IVs detected"); + } + continue; + } + this._ivTrackingSystem.usedIVs.add(ivString); + this._ivTrackingSystem.ivHistory.set(ivString, { + timestamp: Date.now(), + context, + attempt: attempts2 + }); + if (this.sessionId) { + if (!this._ivTrackingSystem.sessionIVs.has(this.sessionId)) { + this._ivTrackingSystem.sessionIVs.set(this.sessionId, /* @__PURE__ */ new Set()); + } + this._ivTrackingSystem.sessionIVs.get(this.sessionId).add(ivString); + } + this._validateRNGQuality(); + this._secureLog("debug", `\u2705 Secure IV generated`, { + context, + attempt: attempts2, + ivSize, + totalIVs: this._ivTrackingSystem.usedIVs.size + }); + return iv; + } + this._secureLog("error", `\u274C Failed to generate unique IV after ${maxAttempts} attempts`, { + context, + totalIVs: this._ivTrackingSystem.usedIVs.size + }); + throw new Error(`Failed to generate unique IV after ${maxAttempts} attempts`); + } + /** + * Validate IV entropy to detect weak RNG + */ + _validateIVEntropy(iv) { + this._ivTrackingSystem.entropyValidation.entropyTests++; + const byteCounts = new Array(256).fill(0); + for (let i = 0; i < iv.length; i++) { + byteCounts[iv[i]]++; + } + const entropyResults = { + shannon: 0, + min: 0, + collision: 0, + compression: 0, + quantum: 0 + }; + let shannonEntropy = 0; + const totalBytes = iv.length; + for (let i = 0; i < 256; i++) { + if (byteCounts[i] > 0) { + const probability = byteCounts[i] / totalBytes; + shannonEntropy -= probability * Math.log2(probability); + } + } + entropyResults.shannon = shannonEntropy; + const maxCount = Math.max(...byteCounts); + const maxProbability = maxCount / totalBytes; + entropyResults.min = -Math.log2(maxProbability); + let collisionSum = 0; + for (let i = 0; i < 256; i++) { + if (byteCounts[i] > 0) { + const probability = byteCounts[i] / totalBytes; + collisionSum += probability * probability; + } + } + entropyResults.collision = -Math.log2(collisionSum); + const ivString = Array.from(iv).map((b) => String.fromCharCode(b)).join(""); + const compressedLength = this._estimateCompressedLength(ivString); + entropyResults.compression = (1 - compressedLength / totalBytes) * 8; + entropyResults.quantum = this._calculateQuantumResistantEntropy(iv); + const hasSuspiciousPatterns = this._detectAdvancedSuspiciousPatterns(iv); + const minEntropyThreshold = this._ivTrackingSystem.entropyValidation.minEntropy; + const isValid = entropyResults.shannon >= minEntropyThreshold && entropyResults.min >= minEntropyThreshold * 0.8 && entropyResults.collision >= minEntropyThreshold * 0.9 && entropyResults.compression >= minEntropyThreshold * 0.7 && entropyResults.quantum >= minEntropyThreshold * 0.6 && !hasSuspiciousPatterns; + if (!isValid) { + this._secureLog("warn", `\u26A0\uFE0F Enhanced IV entropy validation failed`, { + shannon: entropyResults.shannon.toFixed(2), + min: entropyResults.min.toFixed(2), + collision: entropyResults.collision.toFixed(2), + compression: entropyResults.compression.toFixed(2), + quantum: entropyResults.quantum.toFixed(2), + minThreshold: minEntropyThreshold, + hasSuspiciousPatterns + }); + } + return isValid; + } + /** + * Estimate compressed length for entropy calculation + * @param {string} data - Data to estimate compression + * @returns {number} Estimated compressed length + */ + _estimateCompressedLength(data) { + let compressedLength = 0; + let i = 0; + while (i < data.length) { + let matchLength = 0; + let matchDistance = 0; + for (let j = Math.max(0, i - 255); j < i; j++) { + let k = 0; + while (i + k < data.length && data[i + k] === data[j + k] && k < 255) { + k++; + } + if (k > matchLength) { + matchLength = k; + matchDistance = i - j; + } + } + if (matchLength >= 3) { + compressedLength += 3; + i += matchLength; + } else { + compressedLength += 1; + i += 1; + } + } + return compressedLength; + } + /** + * Calculate quantum-resistant entropy + * @param {Uint8Array} data - Data to analyze + * @returns {number} Quantum-resistant entropy score + */ + _calculateQuantumResistantEntropy(data) { + let quantumScore = 0; + const hasQuantumVulnerablePatterns = this._detectQuantumVulnerablePatterns(data); + if (hasQuantumVulnerablePatterns) { + quantumScore -= 2; + } + const bitDistribution = this._analyzeBitDistribution(data); + quantumScore += bitDistribution.score; + const periodicity = this._detectPeriodicity(data); + quantumScore -= periodicity * 0.5; + return Math.max(0, Math.min(8, quantumScore)); + } + /** + * Detect quantum-vulnerable patterns + * @param {Uint8Array} data - Data to analyze + * @returns {boolean} true if quantum-vulnerable patterns found + */ + _detectQuantumVulnerablePatterns(data) { + const patterns = [ + [0, 0, 0, 0, 0, 0, 0, 0], + // All zeros + [255, 255, 255, 255, 255, 255, 255, 255], + // All ones + [0, 1, 0, 1, 0, 1, 0, 1], + // Alternating + [1, 0, 1, 0, 1, 0, 1, 0] + // Alternating reverse + ]; + for (const pattern of patterns) { + for (let i = 0; i <= data.length - pattern.length; i++) { + let match = true; + for (let j = 0; j < pattern.length; j++) { + if (data[i + j] !== pattern[j]) { + match = false; + break; + } + } + if (match) return true; + } + } + return false; + } + /** + * Analyze bit distribution + * @param {Uint8Array} data - Data to analyze + * @returns {Object} Bit distribution analysis + */ + _analyzeBitDistribution(data) { + let ones = 0; + let totalBits = data.length * 8; + for (const byte of data) { + ones += (byte >>> 0).toString(2).split("1").length - 1; + } + const zeroRatio = (totalBits - ones) / totalBits; + const oneRatio = ones / totalBits; + const deviation = Math.abs(0.5 - oneRatio); + const score = Math.max(0, 8 - deviation * 16); + return { score, zeroRatio, oneRatio, deviation }; + } + /** + * Detect periodicity in data + * @param {Uint8Array} data - Data to analyze + * @returns {number} Periodicity score (0-1) + */ + _detectPeriodicity(data) { + if (data.length < 16) return 0; + let maxPeriodicity = 0; + for (let period = 2; period <= data.length / 2; period++) { + let matches = 0; + let totalChecks = 0; + for (let i = 0; i < data.length - period; i++) { + if (data[i] === data[i + period]) { + matches++; + } + totalChecks++; + } + if (totalChecks > 0) { + const periodicity = matches / totalChecks; + maxPeriodicity = Math.max(maxPeriodicity, periodicity); + } + } + return maxPeriodicity; + } + /** + * Enhanced suspicious pattern detection + * @param {Uint8Array} iv - IV to check + * @returns {boolean} true if suspicious patterns found + */ + _detectAdvancedSuspiciousPatterns(iv) { + const patterns = [ + // Sequential patterns + [0, 1, 2, 3, 4, 5, 6, 7], + [255, 254, 253, 252, 251, 250, 249, 248], + // Repeated patterns + [0, 0, 0, 0, 0, 0, 0, 0], + [255, 255, 255, 255, 255, 255, 255, 255], + // Alternating patterns + [0, 255, 0, 255, 0, 255, 0, 255], + [255, 0, 255, 0, 255, 0, 255, 0] + ]; + for (const pattern of patterns) { + for (let i = 0; i <= iv.length - pattern.length; i++) { + let match = true; + for (let j = 0; j < pattern.length; j++) { + if (iv[i + j] !== pattern[j]) { + match = false; + break; + } + } + if (match) return true; + } + } + const entropyMap = this._calculateLocalEntropy(iv); + const lowEntropyRegions = entropyMap.filter((e) => e < 3).length; + return lowEntropyRegions > iv.length * 0.3; + } + /** + * Calculate local entropy for pattern detection + * @param {Uint8Array} data - Data to analyze + * @returns {Array} Array of local entropy values + */ + _calculateLocalEntropy(data) { + const windowSize = 8; + const entropyMap = []; + for (let i = 0; i <= data.length - windowSize; i++) { + const window2 = data.slice(i, i + windowSize); + const charCount = {}; + for (const byte of window2) { + charCount[byte] = (charCount[byte] || 0) + 1; + } + let entropy = 0; + for (const count of Object.values(charCount)) { + const probability = count / windowSize; + entropy -= probability * Math.log2(probability); + } + entropyMap.push(entropy); + } + return entropyMap; + } + /** + * Detect suspicious patterns in IVs + */ + _detectSuspiciousIVPatterns(iv) { + const allZeros = iv.every((byte) => byte === 0); + const allOnes = iv.every((byte) => byte === 255); + if (allZeros || allOnes) { + return true; + } + let sequentialCount = 0; + for (let i = 1; i < iv.length; i++) { + if (iv[i] === iv[i - 1] + 1 || iv[i] === iv[i - 1] - 1) { + sequentialCount++; + } else { + sequentialCount = 0; + } + if (sequentialCount >= 3) { + return true; + } + } + for (let patternLength = 2; patternLength <= Math.floor(iv.length / 2); patternLength++) { + for (let start2 = 0; start2 <= iv.length - patternLength * 2; start2++) { + const pattern1 = iv.slice(start2, start2 + patternLength); + const pattern2 = iv.slice(start2 + patternLength, start2 + patternLength * 2); + if (pattern1.every((byte, index) => byte === pattern2[index])) { + return true; + } + } + } + return false; + } + /** + * Clean up old IVs with strict limits + */ + _cleanupOldIVs() { + const now = Date.now(); + const maxAge = 18e5; + let cleanedCount = 0; + const cleanupBatch = []; + if (this._ivTrackingSystem.ivHistory.size > this._ivTrackingSystem.maxIVHistorySize) { + const ivArray = Array.from(this._ivTrackingSystem.ivHistory.entries()); + const toRemove = ivArray.slice(0, ivArray.length - this._ivTrackingSystem.maxIVHistorySize); + for (const [ivString] of toRemove) { + cleanupBatch.push(ivString); + cleanedCount++; + if (cleanupBatch.length >= 100) { + this._processCleanupBatch(cleanupBatch); + cleanupBatch.length = 0; + } + } + } + for (const [ivString, metadata] of this._ivTrackingSystem.ivHistory.entries()) { + if (now - metadata.timestamp > maxAge) { + cleanupBatch.push(ivString); + cleanedCount++; + if (cleanupBatch.length >= 100) { + this._processCleanupBatch(cleanupBatch); + cleanupBatch.length = 0; + } + } + } + if (cleanupBatch.length > 0) { + this._processCleanupBatch(cleanupBatch); + } + for (const [sessionId, sessionIVs] of this._ivTrackingSystem.sessionIVs.entries()) { + if (sessionIVs.size > this._ivTrackingSystem.maxSessionIVs) { + const ivArray = Array.from(sessionIVs); + const toRemove = ivArray.slice(0, ivArray.length - this._ivTrackingSystem.maxSessionIVs); + for (const ivString of toRemove) { + sessionIVs.delete(ivString); + this._ivTrackingSystem.usedIVs.delete(ivString); + this._ivTrackingSystem.ivHistory.delete(ivString); + cleanedCount++; + } + } + } + if (typeof window.gc === "function" && cleanedCount > 50) { + try { + window.gc(); + } catch (e) { + } + } + if (cleanedCount > 0) { + this._secureLog("debug", `\u{1F9F9} Enhanced cleanup: ${cleanedCount} old IVs removed`, { + cleanedCount, + remainingIVs: this._ivTrackingSystem.usedIVs.size, + remainingHistory: this._ivTrackingSystem.ivHistory.size, + memoryPressure: this._calculateMemoryPressure() + }); + } + } + /** + * Process cleanup batch with constant-time operations + * @param {Array} batch - Batch of items to clean up + */ + _processCleanupBatch(batch) { + for (const item of batch) { + this._ivTrackingSystem.usedIVs.delete(item); + this._ivTrackingSystem.ivHistory.delete(item); + } + } + /** + * Calculate memory pressure for adaptive cleanup + * @returns {number} Memory pressure score (0-100) + */ + _calculateMemoryPressure() { + const totalIVs = this._ivTrackingSystem.usedIVs.size; + const maxAllowed = this._resourceLimits.maxIVHistory; + return Math.min(100, Math.floor(totalIVs / maxAllowed * 100)); + } + /** + * Get IV tracking system statistics + */ + _getIVTrackingStats() { + return { + totalIVs: this._ivTrackingSystem.usedIVs.size, + collisionCount: this._ivTrackingSystem.collisionCount, + entropyTests: this._ivTrackingSystem.entropyValidation.entropyTests, + entropyFailures: this._ivTrackingSystem.entropyValidation.entropyFailures, + rngTests: this._ivTrackingSystem.rngValidation.testsPerformed, + weakRngDetected: this._ivTrackingSystem.rngValidation.weakRngDetected, + emergencyMode: this._ivTrackingSystem.emergencyMode, + sessionCount: this._ivTrackingSystem.sessionIVs.size, + lastCleanup: this._lastIVCleanupTime || 0 + }; + } + /** + * Reset IV tracking system (for testing or emergency recovery) + */ + _resetIVTrackingSystem() { + this._secureLog("warn", "\u{1F504} Resetting IV tracking system"); + this._ivTrackingSystem.usedIVs.clear(); + this._ivTrackingSystem.ivHistory.clear(); + this._ivTrackingSystem.sessionIVs.clear(); + this._ivTrackingSystem.collisionCount = 0; + this._ivTrackingSystem.entropyValidation.entropyTests = 0; + this._ivTrackingSystem.entropyValidation.entropyFailures = 0; + this._ivTrackingSystem.rngValidation.testsPerformed = 0; + this._ivTrackingSystem.rngValidation.weakRngDetected = false; + this._ivTrackingSystem.emergencyMode = false; + this._secureLog("info", "\u2705 IV tracking system reset completed"); + } + /** + * Validate RNG quality + */ + _validateRNGQuality() { + const now = Date.now(); + if (this._ivTrackingSystem.rngValidation.testsPerformed % 1e3 === 0) { + try { + const testIVs = []; + for (let i = 0; i < 100; i++) { + testIVs.push(crypto.getRandomValues(new Uint8Array(12))); + } + const testIVStrings = testIVs.map((iv) => Array.from(iv).map((b) => b.toString(16).padStart(2, "0")).join("")); + const uniqueTestIVs = new Set(testIVStrings); + if (uniqueTestIVs.size < 95) { + this._ivTrackingSystem.rngValidation.weakRngDetected = true; + this._secureLog("error", "\u{1F6A8} CRITICAL: Weak RNG detected in validation test", { + uniqueIVs: uniqueTestIVs.size, + totalTests: testIVs.length + }); + } + this._ivTrackingSystem.rngValidation.lastValidation = now; + } catch (error) { + this._secureLog("error", "\u274C RNG validation failed", { + errorType: error.constructor.name + }); + } + } + this._ivTrackingSystem.rngValidation.testsPerformed++; + } + /** + * Handle mutex timeout with enhanced state validation + */ + _handleMutexTimeout(mutexName, operationId, timeout) { + const mutex = this[`_${mutexName}Mutex`]; + if (!mutex) { + this._secureLog("error", `\u274C Mutex '${mutexName}' not found during timeout handling`); + return; + } + if (mutex.lockId !== operationId) { + this._secureLog("warn", `\u26A0\uFE0F Timeout for different operation ID on mutex '${mutexName}'`, { + expectedOperationId: operationId, + actualLockId: mutex.lockId, + locked: mutex.locked + }); + return; + } + if (!mutex.locked) { + this._secureLog("warn", `\u26A0\uFE0F Timeout for already unlocked mutex '${mutexName}'`, { + operationId + }); + return; + } + try { + const lockDuration = mutex.lockTime ? Date.now() - mutex.lockTime : 0; + this._secureLog("warn", `\u26A0\uFE0F Mutex '${mutexName}' auto-released due to timeout`, { + operationId, + lockDuration, + timeout, + queueLength: mutex.queue.length + }); + mutex.locked = false; + mutex.lockId = null; + mutex.lockTimeout = null; + mutex.lockTime = null; + setTimeout(() => { + try { + this._processNextInQueue(mutexName); + } catch (queueError) { + this._secureLog("error", `\u274C Error processing queue after timeout for mutex '${mutexName}'`, { + errorType: queueError.constructor.name, + errorMessage: queueError.message + }); + } + }, 10); + } catch (error) { + this._secureLog("error", `\u274C Critical error during mutex timeout handling for '${mutexName}'`, { + operationId, + errorType: error.constructor.name, + errorMessage: error.message + }); + try { + this._emergencyUnlockAllMutexes("timeoutHandler"); + } catch (emergencyError) { + this._secureLog("error", `\u274C Emergency unlock failed during timeout handling`, { + originalError: error.message, + emergencyError: emergencyError.message + }); + } + } + } + /** + * Validate mutex system after emergency unlock + */ + _validateMutexSystemAfterEmergencyUnlock() { + const mutexes = ["keyOperation", "cryptoOperation", "connectionOperation"]; + let validationErrors = 0; + this._secureLog("info", "\u{1F50D} Validating mutex system after emergency unlock"); + mutexes.forEach((mutexName) => { + const mutex = this[`_${mutexName}Mutex`]; + if (!mutex) { + validationErrors++; + this._secureLog("error", `\u274C Mutex '${mutexName}' not found after emergency unlock`); + return; + } + if (mutex.locked) { + validationErrors++; + this._secureLog("error", `\u274C Mutex '${mutexName}' still locked after emergency unlock`, { + lockId: mutex.lockId, + lockTime: mutex.lockTime + }); + } + if (mutex.lockId !== null) { + validationErrors++; + this._secureLog("error", `\u274C Mutex '${mutexName}' still has lock ID after emergency unlock`, { + lockId: mutex.lockId + }); + } + if (mutex.lockTimeout !== null) { + validationErrors++; + this._secureLog("error", `\u274C Mutex '${mutexName}' still has timeout after emergency unlock`); + } + if (mutex.queue.length > 0) { + validationErrors++; + this._secureLog("error", `\u274C Mutex '${mutexName}' still has queue items after emergency unlock`, { + queueLength: mutex.queue.length + }); + } + }); + if (this._keySystemState) { + if (this._keySystemState.isInitializing || this._keySystemState.isRotating || this._keySystemState.isDestroying) { + validationErrors++; + this._secureLog("error", `\u274C Key system state not properly reset after emergency unlock`, { + isInitializing: this._keySystemState.isInitializing, + isRotating: this._keySystemState.isRotating, + isDestroying: this._keySystemState.isDestroying + }); + } + } + if (validationErrors === 0) { + this._secureLog("info", "\u2705 Mutex system validation passed after emergency unlock"); + } else { + this._secureLog("error", `\u274C Mutex system validation failed after emergency unlock`, { + validationErrors + }); + setTimeout(() => { + this._emergencyRecoverMutexSystem(); + }, 1e3); + } + } + /** + * NEW: Diagnostics of the mutex system state + */ + _getMutexSystemDiagnostics() { + const diagnostics = { + timestamp: Date.now(), + systemValid: this._validateMutexSystem(), + mutexes: {}, + counters: { ...this._operationCounters }, + keySystemState: { ...this._keySystemState } + }; + const mutexNames = ["keyOperation", "cryptoOperation", "connectionOperation"]; + mutexNames.forEach((mutexName) => { + const mutexPropertyName = `_${mutexName}Mutex`; + const mutex = this[mutexPropertyName]; + if (mutex) { + diagnostics.mutexes[mutexName] = { + locked: mutex.locked, + lockId: mutex.lockId, + queueLength: mutex.queue.length, + hasTimeout: !!mutex.lockTimeout + }; + } else { + diagnostics.mutexes[mutexName] = { error: "not_found" }; + } + }); + return diagnostics; + } + /** + * FULLY FIXED createSecureOffer() + * With race-condition protection and improved security + */ + async createSecureOffer() { + console.log("\u{1F3AF} createSecureOffer called"); + return this._withMutex("connectionOperation", async (operationId) => { + this._secureLog("info", "\u{1F4E4} Creating secure offer with mutex", { + operationId, + connectionAttempts: this.connectionAttempts, + currentState: this.peerConnection?.connectionState || "none" + }); + try { + console.log("\u{1F3AF} PHASE 1: Initialization and validation"); + this._resetNotificationFlags(); + if (!this._checkRateLimit()) { + throw new Error("Connection rate limit exceeded. Please wait before trying again."); + } + this.connectionAttempts = 0; + this.sessionSalt = window.EnhancedSecureCryptoUtils.generateSalt(); + console.log("\u{1F3AF} PHASE 1 completed: Session salt generated"); + this._secureLog("debug", "\u{1F9C2} Session salt generated", { + operationId, + saltLength: this.sessionSalt.length, + isValidSalt: Array.isArray(this.sessionSalt) && this.sessionSalt.length === 64 + }); + console.log("\u{1F3AF} PHASE 2: Secure key generation"); + const keyPairs = await this._generateEncryptionKeys(); + this.ecdhKeyPair = keyPairs.ecdhKeyPair; + this.ecdsaKeyPair = keyPairs.ecdsaKeyPair; + if (!this.ecdhKeyPair?.privateKey || !this.ecdhKeyPair?.publicKey) { + throw new Error("Failed to generate valid ECDH key pair"); + } + if (!this.ecdsaKeyPair?.privateKey || !this.ecdsaKeyPair?.publicKey) { + throw new Error("Failed to generate valid ECDSA key pair"); + } + console.log("\u{1F3AF} PHASE 3: MITM protection and fingerprinting"); + const ecdhFingerprint = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint( + await crypto.subtle.exportKey("spki", this.ecdhKeyPair.publicKey) + ); + const ecdsaFingerprint = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint( + await crypto.subtle.exportKey("spki", this.ecdsaKeyPair.publicKey) + ); + if (!ecdhFingerprint || !ecdsaFingerprint) { + throw new Error("Failed to generate key fingerprints"); + } + this._secureLog("info", "Generated unique key pairs for MITM protection", { + operationId, + hasECDHFingerprint: !!ecdhFingerprint, + hasECDSAFingerprint: !!ecdsaFingerprint, + fingerprintLength: ecdhFingerprint.length, + timestamp: Date.now() + }); + console.log("\u{1F3AF} PHASE 4: Export signed keys"); + const ecdhPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature( + this.ecdhKeyPair.publicKey, + this.ecdsaKeyPair.privateKey, + "ECDH" + ); + const ecdsaPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature( + this.ecdsaKeyPair.publicKey, + this.ecdsaKeyPair.privateKey, + "ECDSA" + ); + if (!ecdhPublicKeyData || typeof ecdhPublicKeyData !== "object") { + this._secureLog("error", "CRITICAL: ECDH key export failed - invalid object structure", { operationId }); + throw new Error("CRITICAL SECURITY FAILURE: ECDH key export validation failed - hard abort required"); + } + if (!ecdhPublicKeyData.keyData || !ecdhPublicKeyData.signature) { + this._secureLog("error", "CRITICAL: ECDH key export incomplete - missing keyData or signature", { + operationId, + hasKeyData: !!ecdhPublicKeyData.keyData, + hasSignature: !!ecdhPublicKeyData.signature + }); + throw new Error("CRITICAL SECURITY FAILURE: ECDH key export incomplete - hard abort required"); + } + if (!ecdsaPublicKeyData || typeof ecdsaPublicKeyData !== "object") { + this._secureLog("error", "CRITICAL: ECDSA key export failed - invalid object structure", { operationId }); + throw new Error("CRITICAL SECURITY FAILURE: ECDSA key export validation failed - hard abort required"); + } + if (!ecdsaPublicKeyData.keyData || !ecdsaPublicKeyData.signature) { + this._secureLog("error", "CRITICAL: ECDSA key export incomplete - missing keyData or signature", { + operationId, + hasKeyData: !!ecdsaPublicKeyData.keyData, + hasSignature: !!ecdsaPublicKeyData.signature + }); + throw new Error("CRITICAL SECURITY FAILURE: ECDSA key export incomplete - hard abort required"); + } + console.log("\u{1F3AF} PHASE 5: Update security features"); + this._updateSecurityFeatures({ + hasEncryption: true, + hasECDH: true, + hasECDSA: true, + hasMutualAuth: true, + hasMetadataProtection: true, + hasEnhancedReplayProtection: true, + hasNonExtractableKeys: true, + hasRateLimiting: true, + hasEnhancedValidation: true, + hasPFS: true + }); + console.log("\u{1F3AF} PHASE 6: Initialize peer connection"); + this.isInitiator = true; + this.onStatusChange("connecting"); + this.createPeerConnection(); + this.dataChannel = this.peerConnection.createDataChannel("securechat", { + ordered: true + }); + this.setupDataChannel(this.dataChannel); + this._secureLog("debug", "\u{1F517} Data channel created", { + operationId, + channelLabel: this.dataChannel.label, + channelOrdered: this.dataChannel.ordered + }); + console.log("\u{1F3AF} PHASE 7: Create SDP offer"); + console.log("\u{1F3AF} Creating WebRTC offer..."); + const offer = await this.peerConnection.createOffer({ + offerToReceiveAudio: false, + offerToReceiveVideo: false + }); + console.log("\u{1F3AF} WebRTC offer created successfully"); + console.log("\u{1F3AF} Setting local description..."); + await this.peerConnection.setLocalDescription(offer); + console.log("\u{1F3AF} Local description set successfully"); + console.log("\u{1F3AF} Extracting DTLS fingerprint..."); + try { + const ourFingerprint = this._extractDTLSFingerprintFromSDP(offer.sdp); + this.expectedDTLSFingerprint = ourFingerprint; + console.log("\u{1F3AF} DTLS fingerprint extracted successfully"); + this._secureLog("info", "Generated DTLS fingerprint for out-of-band verification", { + fingerprint: ourFingerprint, + context: "offer_creation" + }); + this.deliverMessageToUI(`\u{1F510} DTLS fingerprint ready for verification: ${ourFingerprint}`, "system"); + } catch (error) { + this._secureLog("error", "Failed to extract DTLS fingerprint from offer", { error: error.message }); + } + await this.waitForIceGathering(); + this._secureLog("debug", "\u{1F9CA} ICE gathering completed", { + operationId, + iceGatheringState: this.peerConnection.iceGatheringState, + connectionState: this.peerConnection.connectionState + }); + console.log("\u{1F3AF} PHASE 8: Generate SAS for out-of-band verification"); + this.verificationCode = window.EnhancedSecureCryptoUtils.generateVerificationCode(); + console.log("\u{1F3AF} Placeholder verification code generated:", this.verificationCode); + if (!this.verificationCode || this.verificationCode.length < _EnhancedSecureWebRTCManager.SIZES.VERIFICATION_CODE_MIN_LENGTH) { + throw new Error("Failed to generate valid verification code"); + } + console.log("\u{1F3AF} PHASE 9: Mutual authentication challenge"); + const authChallenge = window.EnhancedSecureCryptoUtils.generateMutualAuthChallenge(); + if (!authChallenge) { + throw new Error("Failed to generate mutual authentication challenge"); + } + console.log("\u{1F3AF} PHASE 10: Session ID for MITM protection"); + this.sessionId = Array.from(crypto.getRandomValues(new Uint8Array(_EnhancedSecureWebRTCManager.SIZES.SESSION_ID_LENGTH))).map((b) => b.toString(16).padStart(2, "0")).join(""); + if (!this.sessionId || this.sessionId.length !== _EnhancedSecureWebRTCManager.SIZES.SESSION_ID_LENGTH * 2) { + throw new Error("Failed to generate valid session ID"); + } + this.connectionId = Array.from(crypto.getRandomValues(new Uint8Array(8))).map((b) => b.toString(16).padStart(2, "0")).join(""); + console.log("\u{1F3AF} PHASE 11: Security level calculation"); + let securityLevel; + try { + securityLevel = await this.calculateSecurityLevel(); + } catch (error) { + this._secureLog("warn", "\u26A0\uFE0F Security level calculation failed, using fallback", { + operationId, + errorType: error.constructor.name + }); + securityLevel = { + level: "enhanced", + score: 75, + passedChecks: 10, + totalChecks: 15, + isRealData: false + }; + } + console.log("\u{1F3AF} PHASE 12: Create offer package"); + const currentTimestamp = Date.now(); + console.log("\u{1F3AF} Creating offer package object..."); + const offerPackage = { + // Core information + type: "enhanced_secure_offer", + sdp: this.peerConnection.localDescription.sdp, + version: "4.0", + timestamp: currentTimestamp, + // Cryptographic keys + ecdhPublicKey: ecdhPublicKeyData, + ecdsaPublicKey: ecdsaPublicKeyData, + // Session data + salt: this.sessionSalt, + sessionId: this.sessionId, + connectionId: this.connectionId, + // Authentication + verificationCode: this.verificationCode, + authChallenge, + // Security metadata + securityLevel, + // Additional fields for validation + keyFingerprints: { + ecdh: ecdhFingerprint.substring(0, 16), + // First 16 chars for validation + ecdsa: ecdsaFingerprint.substring(0, 16) + }, + // Optional capabilities info + capabilities: { + supportsFileTransfer: true, + supportsEnhancedSecurity: true, + supportsKeyRotation: true, + supportsFakeTraffic: this.fakeTrafficConfig.enabled, + supportsDecoyChannels: this.decoyChannelConfig.enabled + } + }; + console.log("\u{1F3AF} Offer package object created successfully"); + console.log("\u{1F3AF} PHASE 13: Validate offer package"); + console.log("\u{1F3AF} Validating offer package..."); + try { + const validationResult = this.validateEnhancedOfferData(offerPackage); + console.log("\u{1F3AF} Validation result:", validationResult); + if (!validationResult) { + console.log("\u{1F3AF} Offer package validation FAILED"); + throw new Error("Generated offer package failed validation"); + } + console.log("\u{1F3AF} Offer package validation PASSED"); + } catch (validationError) { + console.log("\u{1F3AF} Validation ERROR:", validationError.message); + throw new Error(`Offer package validation error: ${validationError.message}`); + } + console.log("\u{1F3AF} PHASE 14: Logging and events"); + this._secureLog("info", "Enhanced secure offer created successfully", { + operationId, + version: offerPackage.version, + hasECDSA: true, + hasMutualAuth: true, + hasSessionId: !!offerPackage.sessionId, + securityLevel: securityLevel.level, + timestamp: currentTimestamp, + capabilitiesCount: Object.keys(offerPackage.capabilities).length + }); + document.dispatchEvent(new CustomEvent("new-connection", { + detail: { + type: "offer", + timestamp: currentTimestamp, + securityLevel: securityLevel.level, + operationId + } + })); + console.log("\u{1F3AF} PHASE 15: Return result"); + console.log("\u{1F3AF} createSecureOffer completed successfully, returning offerPackage"); + return offerPackage; + } catch (error) { + this._secureLog("error", "\u274C Enhanced secure offer creation failed in critical section", { + operationId, + errorType: error.constructor.name, + errorMessage: error.message, + phase: this._determineErrorPhase(error), + connectionAttempts: this.connectionAttempts + }); + this._cleanupFailedOfferCreation(); + this.onStatusChange("disconnected"); + throw error; + } + }, 15e3); + } + /** + * HELPER: Determine the phase where the error occurred + */ + _determineErrorPhase(error) { + const message = error.message.toLowerCase(); + if (message.includes("rate limit")) return "rate_limiting"; + if (message.includes("key pair") || message.includes("generate")) return "key_generation"; + if (message.includes("fingerprint")) return "fingerprinting"; + if (message.includes("export") || message.includes("signature")) return "key_export"; + if (message.includes("peer connection")) return "webrtc_setup"; + if (message.includes("offer") || message.includes("sdp")) return "sdp_creation"; + if (message.includes("verification")) return "verification_setup"; + if (message.includes("session")) return "session_setup"; + if (message.includes("validation")) return "package_validation"; + return "unknown"; + } + /** + * Secure cleanup state after failed offer creation + */ + _cleanupFailedOfferCreation() { + try { + this._secureCleanupCryptographicMaterials(); + if (this.peerConnection) { + this.peerConnection.close(); + this.peerConnection = null; + } + if (this.dataChannel) { + this.dataChannel.close(); + this.dataChannel = null; + } + this.isInitiator = false; + this.isVerified = false; + this._updateSecurityFeatures({ + hasEncryption: false, + hasECDH: false, + hasECDSA: false, + hasMutualAuth: false, + hasMetadataProtection: false, + hasEnhancedReplayProtection: false, + hasNonExtractableKeys: false, + hasEnhancedValidation: false, + hasPFS: false + }); + this._forceGarbageCollection(); + this._secureLog("debug", "\u{1F512} Failed offer creation cleanup completed with secure memory wipe"); + } catch (cleanupError) { + this._secureLog("error", "\u274C Error during offer creation cleanup", { + errorType: cleanupError.constructor.name, + errorMessage: cleanupError.message + }); + } + } + /** + * HELPER: Atomic update of security features (if not added yet) + */ + _updateSecurityFeatures(updates) { + const oldFeatures = { ...this.securityFeatures }; + try { + Object.assign(this.securityFeatures, updates); + this._secureLog("debug", "\u{1F527} Security features updated", { + updatedCount: Object.keys(updates).length, + totalFeatures: Object.keys(this.securityFeatures).length + }); + } catch (error) { + this.securityFeatures = oldFeatures; + this._secureLog("error", "\u274C Security features update failed, rolled back", { + errorType: error.constructor.name + }); + throw error; + } + } + /** + * FULLY FIXED METHOD createSecureAnswer() + * With race-condition protection and enhanced security + */ + async createSecureAnswer(offerData) { + console.log("\u{1F3AF} createSecureAnswer called with offerData:", offerData ? "present" : "null"); + return this._withMutex("connectionOperation", async (operationId) => { + this._secureLog("info", "\u{1F4E8} Creating secure answer with mutex", { + operationId, + hasOfferData: !!offerData, + offerType: offerData?.type, + offerVersion: offerData?.version, + offerTimestamp: offerData?.timestamp + }); + try { + this._resetNotificationFlags(); + this._secureLog("debug", "Starting enhanced offer validation", { + operationId, + hasOfferData: !!offerData, + offerType: offerData?.type, + hasECDHKey: !!offerData?.ecdhPublicKey, + hasECDSAKey: !!offerData?.ecdsaPublicKey, + hasSalt: !!offerData?.salt + }); + if (!this.validateEnhancedOfferData(offerData)) { + throw new Error("Invalid connection data format - failed enhanced validation"); + } + if (!window.EnhancedSecureCryptoUtils.rateLimiter.checkConnectionRate(this.rateLimiterId)) { + throw new Error("Connection rate limit exceeded. Please wait before trying again."); + } + if (!offerData.timestamp || !offerData.version) { + throw new Error("Missing required security fields in offer data \u2013 possible MITM attack"); + } + const offerAge = Date.now() - offerData.timestamp; + const MAX_OFFER_AGE = 3e5; + if (offerAge > MAX_OFFER_AGE) { + this._secureLog("error", "Offer data is too old - possible replay attack", { + operationId, + offerAge: Math.round(offerAge / 1e3), + maxAllowedAge: Math.round(MAX_OFFER_AGE / 1e3), + timestamp: offerData.timestamp + }); + if (this.onAnswerError) { + this.onAnswerError("replay_attack", "Offer data is too old \u2013 possible replay attack"); + } + throw new Error("Offer data is too old \u2013 possible replay attack"); + } + if (offerData.version !== "4.0") { + this._secureLog("warn", "Protocol version mismatch detected", { + operationId, + expectedVersion: "4.0", + receivedVersion: offerData.version + }); + if (offerData.version !== "3.0") { + throw new Error(`Unsupported protocol version: ${offerData.version}`); + } + } + this.sessionSalt = offerData.salt; + if (!Array.isArray(this.sessionSalt)) { + throw new Error("Invalid session salt format - must be array"); + } + const expectedSaltLength = offerData.version === "4.0" ? 64 : 32; + if (this.sessionSalt.length !== expectedSaltLength) { + throw new Error(`Invalid session salt length: expected ${expectedSaltLength}, got ${this.sessionSalt.length}`); + } + const saltFingerprint = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(this.sessionSalt); + this._secureLog("info", "Session salt validated successfully", { + operationId, + saltLength: this.sessionSalt.length, + saltFingerprint: saltFingerprint.substring(0, 8) + }); + const keyPairs = await this._generateEncryptionKeys(); + this.ecdhKeyPair = keyPairs.ecdhKeyPair; + this.ecdsaKeyPair = keyPairs.ecdsaKeyPair; + if (!(this.ecdhKeyPair?.privateKey instanceof CryptoKey)) { + this._secureLog("error", "Local ECDH private key is not a CryptoKey", { + operationId, + hasKeyPair: !!this.ecdhKeyPair, + privateKeyType: typeof this.ecdhKeyPair?.privateKey, + privateKeyAlgorithm: this.ecdhKeyPair?.privateKey?.algorithm?.name + }); + throw new Error("Local ECDH private key is not a valid CryptoKey"); + } + let peerECDSAPublicKey; + try { + peerECDSAPublicKey = await crypto.subtle.importKey( + "spki", + new Uint8Array(offerData.ecdsaPublicKey.keyData), + { + name: "ECDSA", + namedCurve: "P-384" + }, + false, + ["verify"] + ); + } catch (error) { + this._throwSecureError(error, "ecdsa_key_import"); + } + let peerECDHPublicKey; + try { + peerECDHPublicKey = await window.EnhancedSecureCryptoUtils.importSignedPublicKey( + offerData.ecdhPublicKey, + peerECDSAPublicKey, + "ECDH" + ); + } catch (error) { + this._secureLog("error", "Failed to import signed ECDH public key", { + operationId, + errorType: error.constructor.name + }); + this._throwSecureError(error, "ecdh_key_import"); + } + if (!(peerECDHPublicKey instanceof CryptoKey)) { + this._secureLog("error", "Peer ECDH public key is not a CryptoKey", { + operationId, + publicKeyType: typeof peerECDHPublicKey, + publicKeyAlgorithm: peerECDHPublicKey?.algorithm?.name + }); + throw new Error("Peer ECDH public key is not a valid CryptoKey"); + } + this.peerPublicKey = peerECDHPublicKey; + let derivedKeys; + try { + derivedKeys = await window.EnhancedSecureCryptoUtils.deriveSharedKeys( + this.ecdhKeyPair.privateKey, + peerECDHPublicKey, + this.sessionSalt + ); + } catch (error) { + this._secureLog("error", "Failed to derive shared keys", { + operationId, + errorType: error.constructor.name + }); + this._throwSecureError(error, "key_derivation"); + } + await this._setEncryptionKeys( + derivedKeys.encryptionKey, + derivedKeys.macKey, + derivedKeys.metadataKey, + derivedKeys.fingerprint + ); + if (!(this.encryptionKey instanceof CryptoKey) || !(this.macKey instanceof CryptoKey) || !(this.metadataKey instanceof CryptoKey)) { + this._secureLog("error", "Invalid key types after derivation", { + operationId, + encryptionKeyType: typeof this.encryptionKey, + macKeyType: typeof this.macKey, + metadataKeyType: typeof this.metadataKey + }); + throw new Error("Invalid key types after derivation"); + } + this.verificationCode = offerData.verificationCode; + this._secureLog("info", "Encryption keys derived and set successfully", { + operationId, + hasEncryptionKey: !!this.encryptionKey, + hasMacKey: !!this.macKey, + hasMetadataKey: !!this.metadataKey, + hasKeyFingerprint: !!this.keyFingerprint, + mitmProtection: "enabled", + signatureVerified: true + }); + this._updateSecurityFeatures({ + hasEncryption: true, + hasECDH: true, + hasECDSA: true, + hasMutualAuth: true, + hasMetadataProtection: true, + hasEnhancedReplayProtection: true, + hasNonExtractableKeys: true, + hasRateLimiting: true, + hasEnhancedValidation: true, + hasPFS: true + }); + this.currentKeyVersion = 0; + this.lastKeyRotation = Date.now(); + this.keyVersions.set(0, { + salt: this.sessionSalt, + timestamp: this.lastKeyRotation, + messageCount: 0 + }); + let authProof; + if (offerData.authChallenge) { + try { + authProof = await window.EnhancedSecureCryptoUtils.createAuthProof( + offerData.authChallenge, + this.ecdsaKeyPair.privateKey, + this.ecdsaKeyPair.publicKey + ); + } catch (error) { + this._secureLog("error", "Failed to create authentication proof", { + operationId, + errorType: error.constructor.name + }); + this._throwSecureError(error, "authentication_proof_creation"); + } + } else { + this._secureLog("warn", "No auth challenge in offer - mutual auth disabled", { + operationId + }); + } + this.isInitiator = false; + this.onStatusChange("connecting"); + console.log("Before onKeyExchange - keyFingerprint:", this.keyFingerprint); + this.onKeyExchange(this.keyFingerprint); + this.createPeerConnection(); + if (this.strictDTLSValidation) { + try { + const receivedFingerprint = this._extractDTLSFingerprintFromSDP(offerData.sdp); + if (this.expectedDTLSFingerprint) { + this._validateDTLSFingerprint(receivedFingerprint, this.expectedDTLSFingerprint, "offer_validation"); + } else { + this.expectedDTLSFingerprint = receivedFingerprint; + this._secureLog("info", "Stored DTLS fingerprint for future validation", { + fingerprint: receivedFingerprint, + context: "first_connection" + }); + } + } catch (error) { + this._secureLog("warn", "DTLS fingerprint validation failed - continuing in fallback mode", { + error: error.message, + context: "offer_validation" + }); + } + } else { + this._secureLog("info", "DTLS fingerprint validation disabled - proceeding without validation"); + } + try { + this._secureLog("debug", "Setting remote description from offer", { + operationId, + sdpLength: offerData.sdp?.length || 0 + }); + await this.peerConnection.setRemoteDescription(new RTCSessionDescription({ + type: "offer", + sdp: offerData.sdp + })); + this._secureLog("debug", "Remote description set successfully", { + operationId, + signalingState: this.peerConnection.signalingState + }); + } catch (error) { + this._secureLog("error", "Failed to set remote description", { + error: error.message, + operationId + }); + this._throwSecureError(error, "webrtc_remote_description"); + } + this._secureLog("debug", "\u{1F517} Remote description set successfully", { + operationId, + connectionState: this.peerConnection.connectionState, + signalingState: this.peerConnection.signalingState + }); + let answer; + try { + answer = await this.peerConnection.createAnswer({ + offerToReceiveAudio: false, + offerToReceiveVideo: false + }); + } catch (error) { + this._throwSecureError(error, "webrtc_create_answer"); + } + try { + await this.peerConnection.setLocalDescription(answer); + } catch (error) { + this._throwSecureError(error, "webrtc_local_description"); + } + try { + const ourFingerprint = this._extractDTLSFingerprintFromSDP(answer.sdp); + this.expectedDTLSFingerprint = ourFingerprint; + this._secureLog("info", "Generated DTLS fingerprint for out-of-band verification", { + fingerprint: ourFingerprint, + context: "answer_creation" + }); + this.deliverMessageToUI(`\u{1F510} DTLS fingerprint ready for verification: ${ourFingerprint}`, "system"); + } catch (error) { + this._secureLog("error", "Failed to extract DTLS fingerprint from answer", { error: error.message }); + } + await this.waitForIceGathering(); + this._secureLog("debug", "\u{1F9CA} ICE gathering completed for answer", { + operationId, + iceGatheringState: this.peerConnection.iceGatheringState, + connectionState: this.peerConnection.connectionState + }); + const ecdhPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature( + this.ecdhKeyPair.publicKey, + this.ecdsaKeyPair.privateKey, + "ECDH" + ); + const ecdsaPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature( + this.ecdsaKeyPair.publicKey, + this.ecdsaKeyPair.privateKey, + "ECDSA" + ); + if (!ecdhPublicKeyData || typeof ecdhPublicKeyData !== "object") { + this._secureLog("error", "CRITICAL: ECDH key export failed - invalid object structure", { operationId }); + throw new Error("CRITICAL SECURITY FAILURE: ECDH key export validation failed - hard abort required"); + } + if (!ecdhPublicKeyData.keyData || !ecdhPublicKeyData.signature) { + this._secureLog("error", "CRITICAL: ECDH key export incomplete - missing keyData or signature", { + operationId, + hasKeyData: !!ecdhPublicKeyData.keyData, + hasSignature: !!ecdhPublicKeyData.signature + }); + throw new Error("CRITICAL SECURITY FAILURE: ECDH key export incomplete - hard abort required"); + } + if (!ecdsaPublicKeyData || typeof ecdsaPublicKeyData !== "object") { + this._secureLog("error", "CRITICAL: ECDSA key export failed - invalid object structure", { operationId }); + throw new Error("CRITICAL SECURITY FAILURE: ECDSA key export validation failed - hard abort required"); + } + if (!ecdsaPublicKeyData.keyData || !ecdsaPublicKeyData.signature) { + this._secureLog("error", "CRITICAL: ECDSA key export incomplete - missing keyData or signature", { + operationId, + hasKeyData: !!ecdsaPublicKeyData.keyData, + hasSignature: !!ecdsaPublicKeyData.signature + }); + throw new Error("CRITICAL SECURITY FAILURE: ECDSA key export incomplete - hard abort required"); + } + let securityLevel; + try { + securityLevel = await this.calculateSecurityLevel(); + } catch (error) { + this._secureLog("warn", "\u26A0\uFE0F Security level calculation failed, using fallback", { + operationId, + errorType: error.constructor.name + }); + securityLevel = { + level: "enhanced", + score: 80, + passedChecks: 12, + totalChecks: 15, + isRealData: false + }; + } + const currentTimestamp = Date.now(); + const answerPackage = { + // Core information + type: "enhanced_secure_answer", + sdp: this.peerConnection.localDescription.sdp, + version: "4.0", + timestamp: currentTimestamp, + // Cryptographic keys + ecdhPublicKey: ecdhPublicKeyData, + ecdsaPublicKey: ecdsaPublicKeyData, + // Authentication + authProof, + // Security metadata + securityLevel, + // Additional security fields + sessionConfirmation: { + saltFingerprint: saltFingerprint.substring(0, 16), + keyDerivationSuccess: true, + mutualAuthEnabled: !!authProof + }, + // Answerer capabilities + capabilities: { + supportsFileTransfer: true, + supportsEnhancedSecurity: true, + supportsKeyRotation: true, + supportsFakeTraffic: this.fakeTrafficConfig.enabled, + supportsDecoyChannels: this.decoyChannelConfig.enabled, + protocolVersion: "4.0" + } + }; + if (!answerPackage.sdp || !answerPackage.ecdhPublicKey || !answerPackage.ecdsaPublicKey) { + throw new Error("Generated answer package is incomplete"); + } + this._secureLog("info", "Enhanced secure answer created successfully", { + operationId, + version: answerPackage.version, + hasECDSA: true, + hasMutualAuth: !!authProof, + hasSessionConfirmation: !!answerPackage.sessionConfirmation, + securityLevel: securityLevel.level, + timestamp: currentTimestamp, + processingTime: currentTimestamp - offerData.timestamp + }); + document.dispatchEvent(new CustomEvent("new-connection", { + detail: { + type: "answer", + timestamp: currentTimestamp, + securityLevel: securityLevel.level, + operationId + } + })); + setTimeout(async () => { + try { + const realSecurityData = await this.calculateAndReportSecurityLevel(); + if (realSecurityData) { + this.notifySecurityUpdate(); + this._secureLog("info", "\u2705 Post-connection security level calculated", { + operationId, + level: realSecurityData.level + }); + } + } catch (error) { + this._secureLog("error", "\u274C Error calculating post-connection security", { + operationId, + errorType: error.constructor.name + }); + } + }, 1e3); + setTimeout(async () => { + if (!this.lastSecurityCalculation || this.lastSecurityCalculation.score < 50) { + this._secureLog("info", "\u{1F504} Retrying security calculation", { + operationId + }); + await this.calculateAndReportSecurityLevel(); + this.notifySecurityUpdate(); + } + }, 3e3); + this.notifySecurityUpdate(); + return answerPackage; + } catch (error) { + this._secureLog("error", "\u274C Enhanced secure answer creation failed in critical section", { + operationId, + errorType: error.constructor.name, + errorMessage: error.message, + phase: this._determineAnswerErrorPhase(error), + offerAge: offerData?.timestamp ? Date.now() - offerData.timestamp : "unknown" + }); + this._cleanupFailedAnswerCreation(); + this.onStatusChange("disconnected"); + if (this.onAnswerError) { + if (error.message.includes("too old") || error.message.includes("replay")) { + this.onAnswerError("replay_attack", error.message); + } else if (error.message.includes("MITM") || error.message.includes("signature")) { + this.onAnswerError("security_violation", error.message); + } else if (error.message.includes("validation") || error.message.includes("format")) { + this.onAnswerError("invalid_format", error.message); + } else { + this.onAnswerError("general_error", error.message); + } + } + throw error; + } + }, 2e4); + } + /** + * HELPER: Determine error phase for answer + */ + _determineAnswerErrorPhase(error) { + const message = error.message.toLowerCase(); + if (message.includes("validation") || message.includes("format")) return "offer_validation"; + if (message.includes("rate limit")) return "rate_limiting"; + if (message.includes("replay") || message.includes("too old")) return "replay_protection"; + if (message.includes("salt")) return "salt_validation"; + if (message.includes("key pair") || message.includes("generate")) return "key_generation"; + if (message.includes("import") || message.includes("ecdsa") || message.includes("ecdh")) return "key_import"; + if (message.includes("signature") || message.includes("mitm")) return "signature_verification"; + if (message.includes("derive") || message.includes("shared")) return "key_derivation"; + if (message.includes("auth") || message.includes("proof")) return "authentication"; + if (message.includes("remote description") || message.includes("local description")) return "webrtc_setup"; + if (message.includes("answer") || message.includes("sdp")) return "sdp_creation"; + if (message.includes("export")) return "key_export"; + if (message.includes("security level")) return "security_calculation"; + return "unknown"; + } + /** + * HELPER: Cleanup state after failed answer creation + */ + /** + * Secure cleanup state after failed answer creation + */ + _cleanupFailedAnswerCreation() { + try { + this._secureCleanupCryptographicMaterials(); + this.currentKeyVersion = 0; + this.keyVersions.clear(); + this.oldKeys.clear(); + if (this.peerConnection) { + this.peerConnection.close(); + this.peerConnection = null; + } + if (this.dataChannel) { + this.dataChannel.close(); + this.dataChannel = null; + } + this.isInitiator = false; + this.isVerified = false; + this.sequenceNumber = 0; + this.expectedSequenceNumber = 0; + this.messageCounter = 0; + this.processedMessageIds.clear(); + this.replayWindow.clear(); + this._updateSecurityFeatures({ + hasEncryption: false, + hasECDH: false, + hasECDSA: false, + hasMutualAuth: false, + hasMetadataProtection: false, + hasEnhancedReplayProtection: false, + hasNonExtractableKeys: false, + hasEnhancedValidation: false, + hasPFS: false + }); + this._forceGarbageCollection(); + this._secureLog("debug", "\u{1F512} Failed answer creation cleanup completed with secure memory wipe"); + } catch (cleanupError) { + this._secureLog("error", "\u274C Error during answer creation cleanup", { + errorType: cleanupError.constructor.name, + errorMessage: cleanupError.message + }); + } + } + /** + * HELPER: Securely set encryption keys (if not set yet) + */ + async _setEncryptionKeys(encryptionKey, macKey, metadataKey, keyFingerprint) { + return this._withMutex("keyOperation", async (operationId) => { + this._secureLog("info", "\u{1F510} Setting encryption keys with mutex", { + operationId + }); + if (!(encryptionKey instanceof CryptoKey) || !(macKey instanceof CryptoKey) || !(metadataKey instanceof CryptoKey)) { + throw new Error("Invalid key types provided"); + } + if (!keyFingerprint || typeof keyFingerprint !== "string") { + throw new Error("Invalid key fingerprint provided"); + } + const oldKeys = { + encryptionKey: this.encryptionKey, + macKey: this.macKey, + metadataKey: this.metadataKey, + keyFingerprint: this.keyFingerprint + }; + try { + this.encryptionKey = encryptionKey; + this.macKey = macKey; + this.metadataKey = metadataKey; + this.keyFingerprint = keyFingerprint; + this.sequenceNumber = 0; + this.expectedSequenceNumber = 0; + this.messageCounter = 0; + this.processedMessageIds.clear(); + this.replayWindow.clear(); + this._secureLog("info", "\u2705 Encryption keys set successfully", { + operationId, + hasAllKeys: !!(this.encryptionKey && this.macKey && this.metadataKey), + hasFingerprint: !!this.keyFingerprint + }); + return true; + } catch (error) { + this.encryptionKey = oldKeys.encryptionKey; + this.macKey = oldKeys.macKey; + this.metadataKey = oldKeys.metadataKey; + this.keyFingerprint = oldKeys.keyFingerprint; + this._secureLog("error", "\u274C Key setting failed, rolled back", { + operationId, + errorType: error.constructor.name + }); + throw error; + } + }); + } + async handleSecureAnswer(answerData) { + console.log("\u{1F3AF} handleSecureAnswer called with answerData:", answerData ? "present" : "null"); + try { + if (!answerData || typeof answerData !== "object" || Array.isArray(answerData)) { + this._secureLog("error", "CRITICAL: Invalid answer data structure", { + hasAnswerData: !!answerData, + answerDataType: typeof answerData, + isArray: Array.isArray(answerData) + }); + throw new Error("CRITICAL SECURITY FAILURE: Answer data must be a non-null object"); + } + if (answerData.type !== "enhanced_secure_answer" || !answerData.sdp) { + this._secureLog("error", "CRITICAL: Invalid answer format", { + type: answerData.type, + hasSdp: !!answerData.sdp + }); + throw new Error("CRITICAL SECURITY FAILURE: Invalid answer format - hard abort required"); + } + if (!answerData.ecdhPublicKey || typeof answerData.ecdhPublicKey !== "object" || Array.isArray(answerData.ecdhPublicKey)) { + this._secureLog("error", "CRITICAL: Invalid ECDH public key structure in answer", { + hasEcdhKey: !!answerData.ecdhPublicKey, + ecdhKeyType: typeof answerData.ecdhPublicKey, + isArray: Array.isArray(answerData.ecdhPublicKey) + }); + throw new Error("CRITICAL SECURITY FAILURE: Missing or invalid ECDH public key structure"); + } + if (!answerData.ecdhPublicKey.keyData || !answerData.ecdhPublicKey.signature) { + this._secureLog("error", "CRITICAL: ECDH key missing keyData or signature in answer", { + hasKeyData: !!answerData.ecdhPublicKey.keyData, + hasSignature: !!answerData.ecdhPublicKey.signature + }); + throw new Error("CRITICAL SECURITY FAILURE: ECDH key missing keyData or signature"); + } + if (!answerData.ecdsaPublicKey || typeof answerData.ecdsaPublicKey !== "object" || Array.isArray(answerData.ecdsaPublicKey)) { + this._secureLog("error", "CRITICAL: Invalid ECDSA public key structure in answer", { + hasEcdsaKey: !!answerData.ecdsaPublicKey, + ecdsaKeyType: typeof answerData.ecdsaPublicKey, + isArray: Array.isArray(answerData.ecdsaPublicKey) + }); + throw new Error("CRITICAL SECURITY FAILURE: Missing or invalid ECDSA public key structure"); + } + if (!answerData.ecdsaPublicKey.keyData || !answerData.ecdsaPublicKey.signature) { + this._secureLog("error", "CRITICAL: ECDSA key missing keyData or signature in answer", { + hasKeyData: !!answerData.ecdsaPublicKey.keyData, + hasSignature: !!answerData.ecdsaPublicKey.signature + }); + throw new Error("CRITICAL SECURITY FAILURE: ECDSA key missing keyData or signature"); + } + if (!answerData.timestamp || !answerData.version) { + throw new Error("Missing required fields in response data \u2013 possible MITM attack"); + } + if (answerData.sessionId && this.sessionId && answerData.sessionId !== this.sessionId) { + window.EnhancedSecureCryptoUtils.secureLog.log("error", "Session ID mismatch detected - possible MITM attack", { + expectedSessionId: this.sessionId, + receivedSessionId: answerData.sessionId + }); + throw new Error("Session ID mismatch \u2013 possible MITM attack"); + } + const answerAge = Date.now() - answerData.timestamp; + if (answerAge > 36e5) { + window.EnhancedSecureCryptoUtils.secureLog.log("error", "Answer data is too old - possible replay attack", { + answerAge, + timestamp: answerData.timestamp + }); + if (this.onAnswerError) { + this.onAnswerError("replay_attack", "Response data is too old \u2013 possible replay attack"); + } + throw new Error("Response data is too old \u2013 possible replay attack"); + } + if (answerData.version !== "4.0") { + window.EnhancedSecureCryptoUtils.secureLog.log("warn", "Incompatible protocol version in answer", { + expectedVersion: "4.0", + receivedVersion: answerData.version + }); + } + const peerECDSAPublicKey = await crypto.subtle.importKey( + "spki", + new Uint8Array(answerData.ecdsaPublicKey.keyData), + { + name: "ECDSA", + namedCurve: "P-384" + }, + false, + ["verify"] + ); + const peerPublicKey = await window.EnhancedSecureCryptoUtils.importPublicKeyFromSignedPackage( + answerData.ecdhPublicKey, + peerECDSAPublicKey + ); + if (!this.sessionSalt || this.sessionSalt.length !== 64) { + window.EnhancedSecureCryptoUtils.secureLog.log("error", "Invalid session salt detected - possible session hijacking", { + saltLength: this.sessionSalt ? this.sessionSalt.length : 0 + }); + throw new Error("Invalid session salt \u2013 possible session hijacking attempt"); + } + const expectedSaltHash = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(this.sessionSalt); + window.EnhancedSecureCryptoUtils.secureLog.log("info", "Session salt integrity verified", { + saltFingerprint: expectedSaltHash.substring(0, 8) + }); + if (!(this.ecdhKeyPair?.privateKey instanceof CryptoKey)) { + window.EnhancedSecureCryptoUtils.secureLog.log("error", "Local ECDH private key is not a CryptoKey in handleSecureAnswer", { + hasKeyPair: !!this.ecdhKeyPair, + privateKeyType: typeof this.ecdhKeyPair?.privateKey, + privateKeyAlgorithm: this.ecdhKeyPair?.privateKey?.algorithm?.name + }); + throw new Error("Local ECDH private key is not a CryptoKey"); + } + if (!(peerPublicKey instanceof CryptoKey)) { + window.EnhancedSecureCryptoUtils.secureLog.log("error", "Peer ECDH public key is not a CryptoKey in handleSecureAnswer", { + publicKeyType: typeof peerPublicKey, + publicKeyAlgorithm: peerPublicKey?.algorithm?.name + }); + throw new Error("Peer ECDH public key is not a CryptoKey"); + } + this.peerPublicKey = peerPublicKey; + if (!this.connectionId) { + this.connectionId = Array.from(crypto.getRandomValues(new Uint8Array(8))).map((b) => b.toString(16).padStart(2, "0")).join(""); + } + const derivedKeys = await window.EnhancedSecureCryptoUtils.deriveSharedKeys( + this.ecdhKeyPair.privateKey, + peerPublicKey, + this.sessionSalt + ); + this.encryptionKey = derivedKeys.encryptionKey; + this.macKey = derivedKeys.macKey; + this.metadataKey = derivedKeys.metadataKey; + this.keyFingerprint = derivedKeys.fingerprint; + this.sequenceNumber = 0; + this.expectedSequenceNumber = 0; + this.messageCounter = 0; + this.processedMessageIds.clear(); + this.replayWindow.clear(); + if (!(this.encryptionKey instanceof CryptoKey) || !(this.macKey instanceof CryptoKey) || !(this.metadataKey instanceof CryptoKey)) { + window.EnhancedSecureCryptoUtils.secureLog.log("error", "Invalid key types after derivation in handleSecureAnswer", { + encryptionKeyType: typeof this.encryptionKey, + macKeyType: typeof this.macKey, + metadataKeyType: typeof this.metadataKey, + encryptionKeyAlgorithm: this.encryptionKey?.algorithm?.name, + macKeyAlgorithm: this.macKey?.algorithm?.name, + metadataKeyAlgorithm: this.metadataKey?.algorithm?.name + }); + throw new Error("Invalid key types after export"); + } + this._secureLog("info", "Encryption keys set in handleSecureAnswer", { + hasEncryptionKey: !!this.encryptionKey, + hasMacKey: !!this.macKey, + hasMetadataKey: !!this.metadataKey, + hasKeyFingerprint: !!this.keyFingerprint, + mitmProtection: "enabled", + signatureVerified: true + }); + this.securityFeatures.hasMutualAuth = true; + this.securityFeatures.hasMetadataProtection = true; + this.securityFeatures.hasEnhancedReplayProtection = true; + this.securityFeatures.hasPFS = true; + this.currentKeyVersion = 0; + this.lastKeyRotation = Date.now(); + this.keyVersions.set(0, { + salt: this.sessionSalt, + timestamp: this.lastKeyRotation, + messageCount: 0 + }); + this.onKeyExchange(this.keyFingerprint); + try { + console.log("Starting SAS computation for Offer side (Answer handler)"); + const remoteFP = this._extractDTLSFingerprintFromSDP(answerData.sdp); + const localFP = this.expectedDTLSFingerprint; + const keyBytes = this._decodeKeyFingerprint(this.keyFingerprint); + console.log("SAS computation parameters:", { + remoteFP: remoteFP ? remoteFP.substring(0, 16) + "..." : "null/undefined", + localFP: localFP ? localFP.substring(0, 16) + "..." : "null/undefined", + keyBytesLength: keyBytes ? keyBytes.length : "null/undefined", + keyBytesType: keyBytes ? keyBytes.constructor.name : "null/undefined" + }); + this.verificationCode = await this._computeSAS(keyBytes, localFP, remoteFP); + this.onStatusChange?.("verifying"); + this.onVerificationRequired(this.verificationCode); + this.pendingSASCode = this.verificationCode; + console.log("\u{1F4E4} SAS code ready to send when data channel opens:", this.verificationCode); + this._secureLog("info", "SAS verification code generated for MITM protection (Offer side)", { + sasCode: this.verificationCode, + localFP: localFP.substring(0, 16) + "...", + remoteFP: remoteFP.substring(0, 16) + "...", + timestamp: Date.now() + }); + } catch (sasError) { + console.error("SAS computation failed in handleSecureAnswer (Offer side):", sasError); + this._secureLog("error", "SAS computation failed in handleSecureAnswer (Offer side)", { + error: sasError.message, + stack: sasError.stack, + timestamp: Date.now() + }); + } + if (this.strictDTLSValidation) { + try { + const receivedFingerprint = this._extractDTLSFingerprintFromSDP(answerData.sdp); + if (this.expectedDTLSFingerprint) { + this._validateDTLSFingerprint(receivedFingerprint, this.expectedDTLSFingerprint, "answer_validation"); + } else { + this.expectedDTLSFingerprint = receivedFingerprint; + this._secureLog("info", "Stored DTLS fingerprint for future validation", { + fingerprint: receivedFingerprint, + context: "first_connection" + }); + } + } catch (error) { + this._secureLog("warn", "DTLS fingerprint validation failed - continuing in fallback mode", { + error: error.message, + context: "answer_validation" + }); + } + } else { + this._secureLog("info", "DTLS fingerprint validation disabled - proceeding without validation"); + } + this._secureLog("debug", "Setting remote description from answer", { + sdpLength: answerData.sdp?.length || 0 + }); + await this.peerConnection.setRemoteDescription({ + type: "answer", + sdp: answerData.sdp + }); + this._secureLog("debug", "Remote description set successfully from answer", { + signalingState: this.peerConnection.signalingState + }); + console.log("Enhanced secure connection established"); + setTimeout(async () => { + try { + const securityData = await this.calculateAndReportSecurityLevel(); + if (securityData) { + console.log("\u2705 Security level calculated after connection:", securityData.level); + this.notifySecurityUpdate(); + } + } catch (error) { + this._secureLog("error", "\u274C Error calculating security after connection:", { errorType: error?.constructor?.name || "Unknown" }); + } + }, 1e3); + setTimeout(async () => { + if (!this.lastSecurityCalculation || this.lastSecurityCalculation.score < 50) { + console.log("\u{1F504} Retrying security calculation..."); + await this.calculateAndReportSecurityLevel(); + this.notifySecurityUpdate(); + } + }, 3e3); + this.notifySecurityUpdate(); + } catch (error) { + this._secureLog("error", "Enhanced secure answer handling failed", { + errorType: error.constructor.name + }); + this.onStatusChange("failed"); + if (this.onAnswerError) { + if (error.message.includes("too old") || error.message.includes("\u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0441\u0442\u0430\u0440\u044B\u0435")) { + this.onAnswerError("replay_attack", error.message); + } else if (error.message.includes("MITM") || error.message.includes("signature") || error.message.includes("\u043F\u043E\u0434\u043F\u0438\u0441\u044C")) { + this.onAnswerError("security_violation", error.message); + } else { + this.onAnswerError("general_error", error.message); + } + } + throw error; + } + } + forceSecurityUpdate() { + console.log("\u{1F504} Force security update requested"); + setTimeout(async () => { + try { + const securityData = await this.calculateAndReportSecurityLevel(); + if (securityData) { + this.notifySecurityUpdate(); + console.log("\u2705 Force security update completed"); + } + } catch (error) { + this._secureLog("error", "\u274C Force security update failed:", { errorType: error?.constructor?.name || "Unknown" }); + } + }, 100); + } + initiateVerification() { + if (this.isInitiator) { + if (!this.verificationInitiationSent) { + this.verificationInitiationSent = true; + this.deliverMessageToUI("\u{1F510} CRITICAL: Compare verification code with peer out-of-band (voice/video/in-person) to prevent MITM attack!", "system"); + this.deliverMessageToUI(`\u{1F510} Your verification code: ${this.verificationCode}`, "system"); + this.deliverMessageToUI("\u{1F510} Ask peer to confirm this exact code before allowing traffic!", "system"); + } + } else { + console.log("\u{1F4E5} Answer side: Waiting for SAS code from Offer side"); + this.deliverMessageToUI("\u{1F4E5} Waiting for verification code from peer...", "system"); + } + } + confirmVerification() { + try { + console.log("\u{1F4E4} confirmVerification - sending local confirmation"); + this.localVerificationConfirmed = true; + const confirmationPayload = { + type: "verification_confirmed", + data: { + timestamp: Date.now(), + verificationMethod: "SAS", + securityLevel: "MITM_PROTECTION_REQUIRED" + } + }; + console.log("\u{1F4E4} Sending verification confirmation:", confirmationPayload); + this.dataChannel.send(JSON.stringify(confirmationPayload)); + if (this.onVerificationStateChange) { + this.onVerificationStateChange({ + localConfirmed: this.localVerificationConfirmed, + remoteConfirmed: this.remoteVerificationConfirmed, + bothConfirmed: this.bothVerificationsConfirmed + }); + } + this._checkBothVerificationsConfirmed(); + this.deliverMessageToUI("\u2705 You confirmed the verification code. Waiting for peer confirmation...", "system"); + this.processMessageQueue(); + } catch (error) { + this._secureLog("error", "\u274C SAS verification failed:", { errorType: error?.constructor?.name || "Unknown" }); + this.deliverMessageToUI("\u274C SAS verification failed", "system"); + } + } + _checkBothVerificationsConfirmed() { + if (this.localVerificationConfirmed && this.remoteVerificationConfirmed && !this.bothVerificationsConfirmed) { + console.log("\u{1F389} Both parties confirmed verification!"); + this.bothVerificationsConfirmed = true; + const bothConfirmedPayload = { + type: "verification_both_confirmed", + data: { + timestamp: Date.now(), + verificationMethod: "SAS", + securityLevel: "MITM_PROTECTION_COMPLETE" + } + }; + console.log("\u{1F4E4} Sending both confirmed notification:", bothConfirmedPayload); + this.dataChannel.send(JSON.stringify(bothConfirmedPayload)); + if (this.onVerificationStateChange) { + this.onVerificationStateChange({ + localConfirmed: this.localVerificationConfirmed, + remoteConfirmed: this.remoteVerificationConfirmed, + bothConfirmed: this.bothVerificationsConfirmed + }); + } + this.deliverMessageToUI("\u{1F389} Both parties confirmed! Opening secure chat in 2 seconds...", "system"); + setTimeout(() => { + this._setVerifiedStatus(true, "MUTUAL_SAS_CONFIRMED", { + code: this.verificationCode, + timestamp: Date.now() + }); + this._enforceVerificationGate("mutual_confirmed", false); + this.onStatusChange?.("verified"); + }, 2e3); + } + } + handleVerificationConfirmed(data) { + console.log("\u{1F4E5} Received verification confirmation from peer"); + this.remoteVerificationConfirmed = true; + this.deliverMessageToUI("\u2705 Peer confirmed the verification code. Waiting for your confirmation...", "system"); + if (this.onVerificationStateChange) { + this.onVerificationStateChange({ + localConfirmed: this.localVerificationConfirmed, + remoteConfirmed: this.remoteVerificationConfirmed, + bothConfirmed: this.bothVerificationsConfirmed + }); + } + this._checkBothVerificationsConfirmed(); + } + handleVerificationBothConfirmed(data) { + console.log("\u{1F4E5} Received both confirmed notification from peer"); + this.bothVerificationsConfirmed = true; + if (this.onVerificationStateChange) { + this.onVerificationStateChange({ + localConfirmed: this.localVerificationConfirmed, + remoteConfirmed: this.remoteVerificationConfirmed, + bothConfirmed: this.bothVerificationsConfirmed + }); + } + this.deliverMessageToUI("\u{1F389} Both parties confirmed! Opening secure chat in 2 seconds...", "system"); + setTimeout(() => { + this._setVerifiedStatus(true, "MUTUAL_SAS_CONFIRMED", { + code: this.verificationCode, + timestamp: Date.now() + }); + this._enforceVerificationGate("mutual_confirmed", false); + this.onStatusChange?.("verified"); + }, 2e3); + } + handleVerificationRequest(data) { + console.log("\u{1F50D} handleVerificationRequest called with:"); + console.log(" - receivedCode:", data.code, "(type:", typeof data.code, ")"); + console.log(" - expectedCode:", this.verificationCode, "(type:", typeof this.verificationCode, ")"); + console.log(" - codesMatch:", data.code === this.verificationCode); + console.log(" - data object:", data); + if (data.code === this.verificationCode) { + const responsePayload = { + type: "verification_response", + data: { + ok: true, + timestamp: Date.now(), + verificationMethod: "SAS", + // Indicate SAS was used + securityLevel: "MITM_PROTECTED" + } + }; + this.dataChannel.send(JSON.stringify(responsePayload)); + if (!this.verificationNotificationSent) { + this.verificationNotificationSent = true; + this.deliverMessageToUI("\u2705 SAS verification successful! MITM protection confirmed. Channel is now secure!", "system"); + } + this.processMessageQueue(); + } else { + console.log("\u274C SAS verification failed - codes do not match, disconnecting"); + const responsePayload = { + type: "verification_response", + data: { + ok: false, + timestamp: Date.now(), + reason: "code_mismatch" + } + }; + this.dataChannel.send(JSON.stringify(responsePayload)); + this._secureLog("error", "SAS verification failed - possible MITM attack", { + receivedCode: data.code, + expectedCode: this.verificationCode, + timestamp: Date.now() + }); + this.deliverMessageToUI("\u274C SAS verification failed! Possible MITM attack detected. Connection aborted for safety!", "system"); + this.disconnect(); + } + } + handleSASCode(data) { + console.log("\u{1F4E5} Received SAS code from Offer side:", data.code); + this.verificationCode = data.code; + this.onStatusChange?.("verifying"); + this.onVerificationRequired(this.verificationCode); + this._secureLog("info", "SAS code received from Offer side", { + sasCode: this.verificationCode, + timestamp: Date.now() + }); + } + handleVerificationResponse(data) { + if (data.ok === true) { + this._secureLog("info", "Mutual SAS verification completed - MITM protection active", { + verificationMethod: data.verificationMethod || "SAS", + securityLevel: data.securityLevel || "MITM_PROTECTED", + timestamp: Date.now() + }); + if (!this.verificationNotificationSent) { + this.verificationNotificationSent = true; + this.deliverMessageToUI("\u2705 Mutual SAS verification complete! MITM protection active. Channel is now secure!", "system"); + } + this.processMessageQueue(); + } else { + this._secureLog("error", "Peer SAS verification failed - connection not secure", { + responseData: data, + timestamp: Date.now() + }); + this.deliverMessageToUI("\u274C Peer verification failed! Connection not secure!", "system"); + this.disconnect(); + } + } + validateOfferData(offerData) { + return offerData && offerData.type === "enhanced_secure_offer" && offerData.sdp && offerData.publicKey && offerData.salt && offerData.verificationCode && Array.isArray(offerData.publicKey) && Array.isArray(offerData.salt) && offerData.salt.length === 32; + } + validateEnhancedOfferData(offerData) { + console.log("\u{1F3AF} validateEnhancedOfferData called with:", offerData ? "valid object" : "null/undefined"); + try { + if (!offerData || typeof offerData !== "object" || Array.isArray(offerData)) { + this._secureLog("error", "CRITICAL: Invalid offer data structure", { + hasOfferData: !!offerData, + offerDataType: typeof offerData, + isArray: Array.isArray(offerData) + }); + throw new Error("CRITICAL SECURITY FAILURE: Offer data must be a non-null object"); + } + const basicFields = ["type", "sdp"]; + for (const field of basicFields) { + if (!offerData[field]) { + throw new Error(`Missing required field: ${field}`); + } + } + if (!["enhanced_secure_offer", "secure_offer"].includes(offerData.type)) { + throw new Error("Invalid offer type"); + } + const isV4Format = offerData.version === "4.0" && offerData.ecdhPublicKey && offerData.ecdsaPublicKey; + if (isV4Format) { + const v4RequiredFields = [ + "ecdhPublicKey", + "ecdsaPublicKey", + "salt", + "verificationCode", + "authChallenge", + "timestamp", + "version", + "securityLevel" + ]; + for (const field of v4RequiredFields) { + if (!offerData[field]) { + throw new Error(`Missing v4.0 field: ${field}`); + } + } + if (!Array.isArray(offerData.salt) || offerData.salt.length !== 64) { + throw new Error("Salt must be exactly 64 bytes for v4.0"); + } + const offerAge = Date.now() - offerData.timestamp; + if (offerAge > 36e5) { + throw new Error("Offer is too old (older than 1 hour)"); + } + if (!offerData.ecdhPublicKey || typeof offerData.ecdhPublicKey !== "object" || Array.isArray(offerData.ecdhPublicKey)) { + this._secureLog("error", "CRITICAL: Invalid ECDH public key structure", { + hasEcdhKey: !!offerData.ecdhPublicKey, + ecdhKeyType: typeof offerData.ecdhPublicKey, + isArray: Array.isArray(offerData.ecdhPublicKey) + }); + throw new Error("CRITICAL SECURITY FAILURE: Invalid ECDH public key structure - hard abort required"); + } + if (!offerData.ecdsaPublicKey || typeof offerData.ecdsaPublicKey !== "object" || Array.isArray(offerData.ecdsaPublicKey)) { + this._secureLog("error", "CRITICAL: Invalid ECDSA public key structure", { + hasEcdsaKey: !!offerData.ecdsaPublicKey, + ecdsaKeyType: typeof offerData.ecdsaPublicKey, + isArray: Array.isArray(offerData.ecdsaPublicKey) + }); + throw new Error("CRITICAL SECURITY FAILURE: Invalid ECDSA public key structure - hard abort required"); + } + if (!offerData.ecdhPublicKey.keyData || !offerData.ecdhPublicKey.signature) { + this._secureLog("error", "CRITICAL: ECDH key missing keyData or signature", { + hasKeyData: !!offerData.ecdhPublicKey.keyData, + hasSignature: !!offerData.ecdhPublicKey.signature + }); + throw new Error("CRITICAL SECURITY FAILURE: ECDH key missing keyData or signature"); + } + if (!offerData.ecdsaPublicKey.keyData || !offerData.ecdsaPublicKey.signature) { + this._secureLog("error", "CRITICAL: ECDSA key missing keyData or signature", { + hasKeyData: !!offerData.ecdsaPublicKey.keyData, + hasSignature: !!offerData.ecdsaPublicKey.signature + }); + throw new Error("CRITICAL SECURITY FAILURE: ECDSA key missing keyData or signature"); + } + if (typeof offerData.verificationCode !== "string" || offerData.verificationCode.length < 6) { + throw new Error("Invalid SAS verification code format - MITM protection required"); + } + this._secureLog("info", "v4.0 offer validation passed", { + version: offerData.version, + hasSecurityLevel: !!offerData.securityLevel?.level, + offerAge: Math.round(offerAge / 1e3) + "s" + }); + } else { + const v3RequiredFields = ["publicKey", "salt", "verificationCode"]; + for (const field of v3RequiredFields) { + if (!offerData[field]) { + throw new Error(`Missing v3.0 field: ${field}`); + } + } + if (!Array.isArray(offerData.salt) || offerData.salt.length !== 32) { + throw new Error("Salt must be exactly 32 bytes for v3.0"); + } + if (!Array.isArray(offerData.publicKey)) { + throw new Error("Invalid public key format for v3.0"); + } + window.EnhancedSecureCryptoUtils.secureLog.log("info", "v3.0 offer validation passed (backward compatibility)", { + version: "v3.0", + legacy: true + }); + } + if (typeof offerData.sdp !== "string" || !offerData.sdp.includes("v=0")) { + throw new Error("Invalid SDP structure"); + } + console.log("\u{1F3AF} validateEnhancedOfferData completed successfully"); + return true; + } catch (error) { + console.log("\u{1F3AF} validateEnhancedOfferData ERROR:", error.message); + this._secureLog("error", "CRITICAL: Security validation failed - hard abort required", { + error: error.message, + errorType: error.constructor.name, + timestamp: Date.now() + }); + throw new Error(`CRITICAL SECURITY VALIDATION FAILURE: ${error.message}`); + } + } + async sendSecureMessage(message) { + const validation = this._validateInputData(message, "sendSecureMessage"); + if (!validation.isValid) { + const errorMessage = `Input validation failed: ${validation.errors.join(", ")}`; + this._secureLog("error", "\u274C Input validation failed in sendSecureMessage", { + errors: validation.errors, + messageType: typeof message + }); + throw new Error(errorMessage); + } + if (!this._checkRateLimit("sendSecureMessage")) { + throw new Error("Rate limit exceeded for secure message sending"); + } + this._enforceVerificationGate("sendSecureMessage"); + if (!this.isConnected()) { + if (validation.sanitizedData && typeof validation.sanitizedData === "object" && validation.sanitizedData.type && validation.sanitizedData.type.startsWith("file_")) { + throw new Error("Connection not ready for file transfer. Please ensure the connection is established and verified."); + } + this.messageQueue.push(validation.sanitizedData); + throw new Error("Connection not ready. Message queued for sending."); + } + return this._withMutex("cryptoOperation", async (operationId) => { + if (!this.isConnected() || !this.isVerified) { + throw new Error("Connection lost during message preparation"); + } + if (!this.encryptionKey || !this.macKey || !this.metadataKey) { + throw new Error("Encryption keys not initialized"); + } + if (!window.EnhancedSecureCryptoUtils.rateLimiter.checkMessageRate(this.rateLimiterId)) { + throw new Error("Message rate limit exceeded (60 messages per minute)"); + } + try { + const textToSend = typeof validation.sanitizedData === "string" ? validation.sanitizedData : JSON.stringify(validation.sanitizedData); + const sanitizedMessage = window.EnhancedSecureCryptoUtils.sanitizeMessage(textToSend); + const messageId = `msg_${Date.now()}_${this.messageCounter++}`; + if (typeof this._createMessageAAD !== "function") { + throw new Error("_createMessageAAD method is not available in sendSecureMessage. Manager may not be fully initialized."); + } + const aad = message.aad || this._createMessageAAD("enhanced_message", { content: sanitizedMessage }); + const encryptedData = await window.EnhancedSecureCryptoUtils.encryptMessage( + sanitizedMessage, + this.encryptionKey, + this.macKey, + this.metadataKey, + messageId, + JSON.parse(aad).sequenceNumber + // Use sequence number from AAD + ); + const payload = { + type: "enhanced_message", + data: encryptedData, + keyVersion: this.currentKeyVersion, + version: "4.0" + }; + this.dataChannel.send(JSON.stringify(payload)); + if (typeof validation.sanitizedData === "string") { + this.deliverMessageToUI(validation.sanitizedData, "sent"); + } + this._secureLog("debug", "\u{1F4E4} Secure message sent successfully", { + operationId, + messageLength: sanitizedMessage.length, + keyVersion: this.currentKeyVersion + }); + } catch (error) { + this._secureLog("error", "\u274C Secure message sending failed", { + operationId, + errorType: error.constructor.name + }); + throw error; + } + }, 2e3); + } + processMessageQueue() { + while (this.messageQueue.length > 0 && this.isConnected() && this.isVerified) { + const message = this.messageQueue.shift(); + this.sendSecureMessage(message).catch(console.error); + } + } + startHeartbeat() { + this._secureLog("info", "\u{1F527} Heartbeat moved to unified scheduler"); + this._heartbeatConfig = { + enabled: true, + interval: _EnhancedSecureWebRTCManager.TIMEOUTS.HEARTBEAT_INTERVAL, + lastHeartbeat: 0 + }; + } + stopHeartbeat() { + if (this._heartbeatConfig) { + this._heartbeatConfig.enabled = false; + } + } + /** + * Stop all active timers and cleanup scheduler + */ + _stopAllTimers() { + this._secureLog("info", "\u{1F527} Stopping all timers and cleanup scheduler"); + if (this._maintenanceScheduler) { + clearInterval(this._maintenanceScheduler); + this._maintenanceScheduler = null; + } + if (this._heartbeatConfig) { + this._heartbeatConfig.enabled = false; + } + if (this._activeTimers) { + this._activeTimers.forEach((timer) => { + if (timer) clearInterval(timer); + }); + this._activeTimers.clear(); + } + this._secureLog("info", "\u2705 All timers stopped successfully"); + } + handleHeartbeat() { + console.log("Heartbeat received - connection alive"); + } + waitForIceGathering() { + return new Promise((resolve) => { + if (this.peerConnection.iceGatheringState === "complete") { + resolve(); + return; + } + const checkState = () => { + if (this.peerConnection && this.peerConnection.iceGatheringState === "complete") { + this.peerConnection.removeEventListener("icegatheringstatechange", checkState); + resolve(); + } + }; + this.peerConnection.addEventListener("icegatheringstatechange", checkState); + setTimeout(() => { + if (this.peerConnection) { + this.peerConnection.removeEventListener("icegatheringstatechange", checkState); + } + resolve(); + }, _EnhancedSecureWebRTCManager.TIMEOUTS.ICE_GATHERING_TIMEOUT); + }); + } + retryConnection() { + console.log(`Retrying connection (attempt ${this.connectionAttempts}/${this.maxConnectionAttempts})`); + this.onStatusChange("retrying"); + } + isConnected() { + const hasDataChannel = !!this.dataChannel; + const dataChannelState = this.dataChannel?.readyState; + const isDataChannelOpen = dataChannelState === "open"; + const isVerified = this.isVerified; + const connectionState = this.peerConnection?.connectionState; + return this.dataChannel && this.dataChannel.readyState === "open" && this.isVerified; + } + getConnectionInfo() { + return { + fingerprint: this.keyFingerprint, + isConnected: this.isConnected(), + isVerified: this.isVerified, + connectionState: this.peerConnection?.connectionState, + iceConnectionState: this.peerConnection?.iceConnectionState, + verificationCode: this.verificationCode + }; + } + disconnect() { + this._stopAllTimers(); + if (this.fileTransferSystem) { + this.fileTransferSystem.cleanup(); + } + this.intentionalDisconnect = true; + window.EnhancedSecureCryptoUtils.secureLog.log("info", "Starting intentional disconnect"); + this.sendDisconnectNotification(); + setTimeout(() => { + this.sendDisconnectNotification(); + }, 100); + document.dispatchEvent(new CustomEvent("peer-disconnect", { + detail: { + reason: "user_disconnect", + timestamp: Date.now() + } + })); + } + handleUnexpectedDisconnect() { + this.sendDisconnectNotification(); + this.isVerified = false; + if (!this.disconnectNotificationSent) { + this.disconnectNotificationSent = true; + this.deliverMessageToUI("\u{1F50C} Connection lost. Attempting to reconnect...", "system"); + } + if (this.fileTransferSystem) { + console.log("\u{1F9F9} Cleaning up file transfer system on unexpected disconnect..."); + this.fileTransferSystem.cleanup(); + this.fileTransferSystem = null; + } + document.dispatchEvent(new CustomEvent("peer-disconnect", { + detail: { + reason: "connection_lost", + timestamp: Date.now() + } + })); + } + sendDisconnectNotification() { + try { + if (this.dataChannel && this.dataChannel.readyState === "open") { + const notification = { + type: "peer_disconnect", + timestamp: Date.now(), + reason: this.intentionalDisconnect ? "user_disconnect" : "connection_lost" + }; + for (let i = 0; i < 3; i++) { + try { + this.dataChannel.send(JSON.stringify(notification)); + window.EnhancedSecureCryptoUtils.secureLog.log("info", "Disconnect notification sent", { + reason: notification.reason, + attempt: i + 1 + }); + break; + } catch (sendError) { + if (i === 2) { + window.EnhancedSecureCryptoUtils.secureLog.log("error", "Failed to send disconnect notification", { + error: sendError.message + }); + } + } + } + } + } catch (error) { + window.EnhancedSecureCryptoUtils.secureLog.log("error", "Could not send disconnect notification", { + error: error.message + }); + } + } + attemptReconnection() { + if (!this.reconnectionFailedNotificationSent) { + this.reconnectionFailedNotificationSent = true; + this.deliverMessageToUI("\u274C Unable to reconnect. A new connection is required.", "system"); + } + } + handlePeerDisconnectNotification(data) { + const reason = data.reason || "unknown"; + const reasonText = reason === "user_disconnect" ? "manually disconnected." : "connection lost."; + if (!this.peerDisconnectNotificationSent) { + this.peerDisconnectNotificationSent = true; + this.deliverMessageToUI(`\u{1F44B} Peer ${reasonText}`, "system"); + } + this.onStatusChange("peer_disconnected"); + this.intentionalDisconnect = false; + this.isVerified = false; + this.stopHeartbeat(); + this.onKeyExchange(""); + this.onVerificationRequired(""); + document.dispatchEvent(new CustomEvent("peer-disconnect", { + detail: { + reason, + timestamp: Date.now() + } + })); + setTimeout(() => { + this.disconnect(); + }, 2e3); + window.EnhancedSecureCryptoUtils.secureLog.log("info", "Peer disconnect notification processed", { + reason + }); + } + /** + * Secure disconnect with complete memory cleanup + */ + disconnect() { + this.stopHeartbeat(); + this.isVerified = false; + this.processedMessageIds.clear(); + this.messageCounter = 0; + this._secureCleanupCryptographicMaterials(); + this.keyVersions.clear(); + this.oldKeys.clear(); + this.currentKeyVersion = 0; + this.lastKeyRotation = Date.now(); + this.sequenceNumber = 0; + this.expectedSequenceNumber = 0; + this.replayWindow.clear(); + this.securityFeatures = { + hasEncryption: true, + hasECDH: true, + hasECDSA: true, + hasMutualAuth: true, + hasMetadataProtection: true, + hasEnhancedReplayProtection: true, + hasNonExtractableKeys: true, + hasRateLimiting: true, + hasEnhancedValidation: true, + hasPFS: true + }; + if (this.dataChannel) { + this.dataChannel.close(); + this.dataChannel = null; + } + if (this.peerConnection) { + this.peerConnection.close(); + this.peerConnection = null; + } + if (this.messageQueue && this.messageQueue.length > 0) { + this.messageQueue.forEach((message, index) => { + this._secureWipeMemory(message, `messageQueue[${index}]`); + }); + this.messageQueue = []; + } + this._forceGarbageCollection(); + document.dispatchEvent(new CustomEvent("connection-cleaned", { + detail: { + timestamp: Date.now(), + reason: this.intentionalDisconnect ? "user_cleanup" : "automatic_cleanup" + } + })); + this.onStatusChange("disconnected"); + this.onKeyExchange(""); + this.onVerificationRequired(""); + this._secureLog("info", "\u{1F512} Connection securely cleaned up with complete memory wipe"); + this.intentionalDisconnect = false; + } + // Public method to send files + async sendFile(file) { + this._enforceVerificationGate("sendFile"); + if (!this.isConnected()) { + throw new Error("Connection not ready for file transfer. Please ensure the connection is established."); + } + if (!this.fileTransferSystem) { + console.log("\u{1F504} File transfer system not initialized, attempting to initialize..."); + this.initializeFileTransfer(); + await new Promise((resolve) => setTimeout(resolve, 500)); + if (!this.fileTransferSystem) { + throw new Error("File transfer system could not be initialized. Please try reconnecting."); + } + } + if (!this.encryptionKey || !this.macKey) { + throw new Error("Encryption keys not ready. Please wait for connection to be fully established."); + } + console.log("\u{1F50D} Debug: File transfer system in sendFile:", { + hasFileTransferSystem: !!this.fileTransferSystem, + fileTransferSystemType: this.fileTransferSystem.constructor?.name, + hasWebrtcManager: !!this.fileTransferSystem.webrtcManager, + webrtcManagerType: this.fileTransferSystem.webrtcManager?.constructor?.name + }); + try { + console.log("\u{1F680} Starting file transfer for:", file.name, `(${(file.size / 1024 / 1024).toFixed(2)} MB)`); + const fileId = await this.fileTransferSystem.sendFile(file); + console.log("\u2705 File transfer initiated successfully with ID:", fileId); + return fileId; + } catch (error) { + this._secureLog("error", "\u274C File transfer error:", { errorType: error?.constructor?.name || "Unknown" }); + if (error.message.includes("Connection not ready")) { + throw new Error("Connection not ready for file transfer. Check connection status."); + } else if (error.message.includes("Encryption keys not initialized")) { + throw new Error("Encryption keys not initialized. Try reconnecting."); + } else if (error.message.includes("Transfer timeout")) { + throw new Error("File transfer timeout. Check connection and try again."); + } else { + throw error; + } + } + } + // Get active file transfers + getFileTransfers() { + if (!this.fileTransferSystem) { + return { sending: [], receiving: [] }; + } + try { + let sending = []; + let receiving = []; + if (typeof this.fileTransferSystem.getActiveTransfers === "function") { + sending = this.fileTransferSystem.getActiveTransfers(); + } else { + this._secureLog("warn", "\u26A0\uFE0F getActiveTransfers method not available in file transfer system"); + } + if (typeof this.fileTransferSystem.getReceivingTransfers === "function") { + receiving = this.fileTransferSystem.getReceivingTransfers(); + } else { + this._secureLog("warn", "\u26A0\uFE0F getReceivingTransfers method not available in file transfer system"); + } + return { + sending: sending || [], + receiving: receiving || [] + }; + } catch (error) { + this._secureLog("error", "\u274C Error getting file transfers:", { errorType: error?.constructor?.name || "Unknown" }); + return { sending: [], receiving: [] }; + } + } + // Get file transfer system status + getFileTransferStatus() { + if (!this.fileTransferSystem) { + return { + initialized: false, + status: "not_initialized", + message: "File transfer system not initialized" + }; + } + const activeTransfers = this.fileTransferSystem.getActiveTransfers(); + const receivingTransfers = this.fileTransferSystem.getReceivingTransfers(); + return { + initialized: true, + status: "ready", + activeTransfers: activeTransfers.length, + receivingTransfers: receivingTransfers.length, + totalTransfers: activeTransfers.length + receivingTransfers.length + }; + } + // Cancel file transfer + cancelFileTransfer(fileId) { + if (!this.fileTransferSystem) return false; + return this.fileTransferSystem.cancelTransfer(fileId); + } + // Force cleanup of file transfer system + cleanupFileTransferSystem() { + if (this.fileTransferSystem) { + console.log("\u{1F9F9} Force cleaning up file transfer system..."); + this.fileTransferSystem.cleanup(); + this.fileTransferSystem = null; + return true; + } + return false; + } + // Reinitialize file transfer system + reinitializeFileTransfer() { + try { + console.log("\u{1F504} Reinitializing file transfer system..."); + if (this.fileTransferSystem) { + this.fileTransferSystem.cleanup(); + } + this.initializeFileTransfer(); + return true; + } catch (error) { + this._secureLog("error", "\u274C Failed to reinitialize file transfer system:", { errorType: error?.constructor?.name || "Unknown" }); + return false; + } + } + // Set file transfer callbacks + setFileTransferCallbacks(onProgress, onReceived, onError) { + this.onFileProgress = onProgress; + this.onFileReceived = onReceived; + this.onFileError = onError; + console.log("\u{1F527} File transfer callbacks set:", { + hasProgress: !!onProgress, + hasReceived: !!onReceived, + hasError: !!onError + }); + if (this.fileTransferSystem) { + console.log("\u{1F504} Reinitializing file transfer system with new callbacks..."); + this.initializeFileTransfer(); + } + } + // ============================================ + // SESSION ACTIVATION HANDLING + // ============================================ + async handleSessionActivation(sessionData) { + try { + console.log("\u{1F510} Handling session activation:", sessionData); + this.currentSession = sessionData; + this.sessionManager = sessionData.sessionManager; + const hasKeys = !!(this.encryptionKey && this.macKey); + const hasSession = !!(this.sessionManager && (this.sessionManager.hasActiveSession?.() || sessionData.sessionId)); + console.log("\u{1F50D} Session activation status:", { + hasKeys, + hasSession, + sessionType: sessionData.sessionType, + isDemo: sessionData.isDemo + }); + if (hasSession) { + console.log("\u{1F513} Session activated - forcing connection status to connected"); + this.onStatusChange("connected"); + console.log("\u26A0\uFE0F Session activated but NOT verified - cryptographic verification still required"); + } + setTimeout(() => { + try { + this.initializeFileTransfer(); + } catch (error) { + this._secureLog("warn", "\u26A0\uFE0F File transfer initialization failed during session activation:", { details: error.message }); + } + }, 1e3); + console.log("\u2705 Session activation handled successfully"); + if (this.fileTransferSystem && this.isConnected()) { + console.log("\u{1F504} Synchronizing file transfer keys after session activation..."); + if (typeof this.fileTransferSystem.onSessionUpdate === "function") { + this.fileTransferSystem.onSessionUpdate({ + keyFingerprint: this.keyFingerprint, + sessionSalt: this.sessionSalt, + hasMacKey: !!this.macKey + }); + } + } + } catch (error) { + this._secureLog("error", "\u274C Failed to handle session activation:", { errorType: error?.constructor?.name || "Unknown" }); + } + } + // Method to check readiness of file transfers + checkFileTransferReadiness() { + const status = { + hasFileTransferSystem: !!this.fileTransferSystem, + hasDataChannel: !!this.dataChannel, + dataChannelState: this.dataChannel?.readyState, + isConnected: this.isConnected(), + isVerified: this.isVerified, + hasEncryptionKey: !!this.encryptionKey, + hasMacKey: !!this.macKey, + ready: false + }; + status.ready = status.hasFileTransferSystem && status.hasDataChannel && status.dataChannelState === "open" && status.isConnected && status.isVerified; + console.log("\u{1F50D} File transfer readiness check:", status); + return status; + } + // Method to force re-initialize file transfer system + forceReinitializeFileTransfer() { + try { + console.log("\u{1F504} Force reinitializing file transfer system..."); + if (this.fileTransferSystem) { + this.fileTransferSystem.cleanup(); + this.fileTransferSystem = null; + } + setTimeout(() => { + this.initializeFileTransfer(); + }, 500); + return true; + } catch (error) { + this._secureLog("error", "\u274C Failed to force reinitialize file transfer:", { errorType: error?.constructor?.name || "Unknown" }); + return false; + } + } + // Method to get diagnostic information + getFileTransferDiagnostics() { + const diagnostics = { + timestamp: (/* @__PURE__ */ new Date()).toISOString(), + webrtcManager: { + hasDataChannel: !!this.dataChannel, + dataChannelState: this.dataChannel?.readyState, + isConnected: this.isConnected(), + isVerified: this.isVerified, + isInitiator: this.isInitiator, + hasEncryptionKey: !!this.encryptionKey, + hasMacKey: !!this.macKey, + hasMetadataKey: !!this.metadataKey, + hasKeyFingerprint: !!this.keyFingerprint, + hasSessionSalt: !!this.sessionSalt + }, + fileTransferSystem: null, + globalState: { + fileTransferActive: this._fileTransferActive || false, + hasFileTransferSystem: !!this.fileTransferSystem, + fileTransferSystemType: this.fileTransferSystem ? "EnhancedSecureFileTransfer" : "none" + } + }; + if (this.fileTransferSystem) { + try { + diagnostics.fileTransferSystem = this.fileTransferSystem.getSystemStatus(); + } catch (error) { + diagnostics.fileTransferSystem = { error: error.message }; + } + } + return diagnostics; + } + getSupportedFileTypes() { + if (!this.fileTransferSystem) { + return { error: "File transfer system not initialized" }; + } + try { + return this.fileTransferSystem.getSupportedFileTypes(); + } catch (error) { + return { error: error.message }; + } + } + validateFile(file) { + if (!this.fileTransferSystem) { + return { + isValid: false, + errors: ["File transfer system not initialized"], + fileType: null, + fileSize: file?.size || 0, + formattedSize: "0 B" + }; + } + try { + return this.fileTransferSystem.validateFile(file); + } catch (error) { + return { + isValid: false, + errors: [error.message], + fileType: null, + fileSize: file?.size || 0, + formattedSize: "0 B" + }; + } + } + getFileTypeInfo() { + if (!this.fileTransferSystem) { + return { error: "File transfer system not initialized" }; + } + try { + return this.fileTransferSystem.getFileTypeInfo(); + } catch (error) { + return { error: error.message }; + } + } + async forceInitializeFileTransfer(options = {}) { + const abortController = new AbortController(); + const { signal = abortController.signal, timeout = 6e3 } = options; + if (signal && signal !== abortController.signal) { + signal.addEventListener("abort", () => abortController.abort()); + } + try { + if (!this.isVerified) { + throw new Error("Connection not verified"); + } + if (!this.dataChannel || this.dataChannel.readyState !== "open") { + throw new Error("Data channel not open"); + } + if (!this.encryptionKey || !this.macKey) { + throw new Error("Encryption keys not ready"); + } + if (this.fileTransferSystem) { + this.fileTransferSystem.cleanup(); + this.fileTransferSystem = null; + } + this.initializeFileTransfer(); + let attempts2 = 0; + const maxAttempts = 50; + const checkInterval = 100; + const maxWaitTime = maxAttempts * checkInterval; + const initializationPromise = new Promise((resolve, reject) => { + const checkInitialization = () => { + if (abortController.signal.aborted) { + reject(new Error("Operation cancelled")); + return; + } + if (this.fileTransferSystem) { + resolve(true); + return; + } + if (attempts2 >= maxAttempts) { + reject(new Error(`Initialization timeout after ${maxWaitTime}ms`)); + return; + } + attempts2++; + setTimeout(checkInitialization, checkInterval); + }; + checkInitialization(); + }); + await Promise.race([ + initializationPromise, + new Promise( + (_, reject) => setTimeout(() => reject(new Error(`Global timeout after ${timeout}ms`)), timeout) + ) + ]); + if (this.fileTransferSystem) { + return true; + } else { + throw new Error("Force initialization timeout"); + } + } catch (error) { + if (error.name === "AbortError" || error.message.includes("cancelled")) { + this._secureLog("info", "\u23F9\uFE0F File transfer initialization cancelled by user"); + return { cancelled: true }; + } + this._secureLog("error", "\u274C Force file transfer initialization failed:", { + errorType: error?.constructor?.name || "Unknown", + message: error.message, + attempts + }); + return { error: error.message, attempts }; + } + } + cancelFileTransferInitialization() { + try { + if (this.fileTransferSystem) { + this.fileTransferSystem.cleanup(); + this.fileTransferSystem = null; + this._fileTransferActive = false; + this._secureLog("info", "\u23F9\uFE0F File transfer initialization cancelled"); + return true; + } + return false; + } catch (error) { + this._secureLog("error", "\u274C Failed to cancel file transfer initialization:", { + errorType: error?.constructor?.name || "Unknown" + }); + return false; + } + } + getFileTransferSystemStatus() { + if (!this.fileTransferSystem) { + return { available: false, status: "not_initialized" }; + } + try { + const status = this.fileTransferSystem.getSystemStatus(); + return { + available: true, + status: status.status || "unknown", + activeTransfers: status.activeTransfers || 0, + receivingTransfers: status.receivingTransfers || 0, + systemType: "EnhancedSecureFileTransfer" + }; + } catch (error) { + this._secureLog("error", "\u274C Failed to get file transfer system status:", { + errorType: error?.constructor?.name || "Unknown" + }); + return { available: false, status: "error", error: error.message }; + } + } + _validateNestedEncryptionSecurity() { + if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey) { + try { + const testIV1 = this._generateSecureIV(_EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE, "securityTest1"); + const testIV2 = this._generateSecureIV(_EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE, "securityTest2"); + if (testIV1.every((byte, index) => byte === testIV2[index])) { + this._secureLog("error", "\u274C CRITICAL: Nested encryption security validation failed - IVs are identical!"); + return false; + } + const stats = this._getIVTrackingStats(); + if (stats.totalIVs < 2) { + this._secureLog("error", "\u274C CRITICAL: IV tracking system not working properly"); + return false; + } + this._secureLog("info", "\u2705 Nested encryption security validation passed - secure IV generation working"); + return true; + } catch (error) { + this._secureLog("error", "\u274C CRITICAL: Nested encryption security validation failed:", { + errorType: error.constructor.name, + errorMessage: error.message + }); + return false; + } + } + return true; + } +}; +var SecureKeyStorage = class { + constructor() { + this._keyStore = /* @__PURE__ */ new WeakMap(); + this._keyMetadata = /* @__PURE__ */ new Map(); + this._keyReferences = /* @__PURE__ */ new Map(); + this._storageMasterKey = null; + this._initializeStorageMaster(); + setTimeout(() => { + if (!this.validateStorageIntegrity()) { + console.error("\u274C CRITICAL: Key storage integrity check failed"); + } + }, 100); + } + async _initializeStorageMaster() { + this._storageMasterKey = await crypto.subtle.generateKey( + { name: "AES-GCM", length: 256 }, + false, + ["encrypt", "decrypt"] + ); + } + async storeKey(keyId, cryptoKey, metadata = {}) { + if (!(cryptoKey instanceof CryptoKey)) { + throw new Error("Only CryptoKey objects can be stored"); + } + try { + if (!cryptoKey.extractable) { + this._keyReferences.set(keyId, cryptoKey); + this._keyMetadata.set(keyId, { + ...metadata, + created: Date.now(), + lastAccessed: Date.now(), + extractable: false, + encrypted: false + // Mark as not encrypted + }); + return true; + } + const keyData = await crypto.subtle.exportKey("jwk", cryptoKey); + const encryptedKeyData = await this._encryptKeyData(keyData); + if (!encryptedKeyData || encryptedKeyData.byteLength === 0) { + throw new Error("Failed to encrypt extractable key data"); + } + const storageObject = { + id: keyId, + encryptedData: encryptedKeyData, + algorithm: cryptoKey.algorithm, + usages: cryptoKey.usages, + extractable: cryptoKey.extractable, + type: cryptoKey.type, + timestamp: Date.now() + }; + this._keyStore.set(cryptoKey, storageObject); + this._keyReferences.set(keyId, cryptoKey); + this._keyMetadata.set(keyId, { + ...metadata, + created: Date.now(), + lastAccessed: Date.now(), + extractable: true, + encrypted: true + // Mark extractable keys as encrypted + }); + return true; + } catch (error) { + console.error("Failed to store key securely:", error); + return false; + } + } + async retrieveKey(keyId) { + const metadata = this._keyMetadata.get(keyId); + if (!metadata) { + return null; + } + metadata.lastAccessed = Date.now(); + if (!metadata.encrypted) { + if (metadata.extractable === false) { + return this._keyReferences.get(keyId); + } else { + this._secureLog("error", "\u274C SECURITY VIOLATION: Extractable key marked as non-encrypted", { + keyId, + extractable: metadata.extractable, + encrypted: metadata.encrypted + }); + return null; + } + } + try { + const cryptoKey = this._keyReferences.get(keyId); + const storedData = this._keyStore.get(cryptoKey); + if (!storedData) { + return null; + } + const decryptedKeyData = await this._decryptKeyData(storedData.encryptedData); + const recreatedKey = await crypto.subtle.importKey( + "jwk", + decryptedKeyData, + storedData.algorithm, + storedData.extractable, + storedData.usages + ); + return recreatedKey; + } catch (error) { + console.error("Failed to retrieve key:", error); + return null; + } + } + async _encryptKeyData(keyData) { + const dataToEncrypt = typeof keyData === "object" ? JSON.stringify(keyData) : keyData; + const encoder = new TextEncoder(); + const data = encoder.encode(dataToEncrypt); + const iv = crypto.getRandomValues(new Uint8Array(12)); + const encryptedData = await crypto.subtle.encrypt( + { name: "AES-GCM", iv }, + this._storageMasterKey, + data + ); + const result = new Uint8Array(iv.length + encryptedData.byteLength); + result.set(iv, 0); + result.set(new Uint8Array(encryptedData), iv.length); + return result; + } + async _decryptKeyData(encryptedData) { + const iv = encryptedData.slice(0, 12); + const data = encryptedData.slice(12); + const decryptedData = await crypto.subtle.decrypt( + { name: "AES-GCM", iv }, + this._storageMasterKey, + data + ); + const decoder = new TextDecoder(); + const jsonString = decoder.decode(decryptedData); + try { + return JSON.parse(jsonString); + } catch { + return decryptedData; + } + } + secureWipe(keyId) { + const cryptoKey = this._keyReferences.get(keyId); + if (cryptoKey) { + this._keyStore.delete(cryptoKey); + this._keyReferences.delete(keyId); + this._keyMetadata.delete(keyId); + } + if (typeof window.gc === "function") { + window.gc(); + } + } + secureWipeAll() { + this._keyReferences.clear(); + this._keyMetadata.clear(); + this._keyStore = /* @__PURE__ */ new WeakMap(); + if (typeof window.gc === "function") { + window.gc(); + } + } + // Validate storage integrity + validateStorageIntegrity() { + const violations = []; + for (const [keyId, metadata] of this._keyMetadata.entries()) { + if (metadata.extractable === true && metadata.encrypted !== true) { + violations.push({ + keyId, + type: "EXTRACTABLE_KEY_NOT_ENCRYPTED", + metadata + }); + } + if (metadata.extractable === false && metadata.encrypted === true) { + violations.push({ + keyId, + type: "NON_EXTRACTABLE_KEY_ENCRYPTED", + metadata + }); + } + } + if (violations.length > 0) { + console.error("\u274C Storage integrity violations detected:", violations); + return false; + } + return true; + } + getStorageStats() { + return { + totalKeys: this._keyReferences.size, + metadata: Array.from(this._keyMetadata.entries()).map(([id, meta]) => ({ + id, + created: meta.created, + lastAccessed: meta.lastAccessed, + age: Date.now() - meta.created + })) + }; + } + // Method _generateNextSequenceNumber moved to constructor area for early availability + /** + * Validate incoming message sequence number + * This prevents replay attacks and ensures message ordering + */ + _validateIncomingSequenceNumber(receivedSeq, context = "unknown") { + try { + if (!this.replayProtectionEnabled) { + return true; + } + if (receivedSeq < this.expectedSequenceNumber - this.replayWindowSize) { + this._secureLog("warn", "\u26A0\uFE0F Sequence number too old - possible replay attack", { + received: receivedSeq, + expected: this.expectedSequenceNumber, + context, + timestamp: Date.now() + }); + return false; + } + if (receivedSeq > this.expectedSequenceNumber + this.maxSequenceGap) { + this._secureLog("warn", "\u26A0\uFE0F Sequence number gap too large - possible DoS attack", { + received: receivedSeq, + expected: this.expectedSequenceNumber, + gap: receivedSeq - this.expectedSequenceNumber, + context, + timestamp: Date.now() + }); + return false; + } + if (this.replayWindow.has(receivedSeq)) { + this._secureLog("warn", "\u26A0\uFE0F Duplicate sequence number detected - replay attack", { + received: receivedSeq, + context, + timestamp: Date.now() + }); + return false; + } + this.replayWindow.add(receivedSeq); + if (this.replayWindow.size > this.replayWindowSize) { + const oldestSeq = Math.min(...this.replayWindow); + this.replayWindow.delete(oldestSeq); + } + if (receivedSeq === this.expectedSequenceNumber) { + this.expectedSequenceNumber++; + while (this.replayWindow.has(this.expectedSequenceNumber - this.replayWindowSize - 1)) { + this.replayWindow.delete(this.expectedSequenceNumber - this.replayWindowSize - 1); + } + } + this._secureLog("debug", "\u2705 Sequence number validation successful", { + received: receivedSeq, + expected: this.expectedSequenceNumber, + context, + timestamp: Date.now() + }); + return true; + } catch (error) { + this._secureLog("error", "\u274C Sequence number validation failed", { + error: error.message, + context, + timestamp: Date.now() + }); + return false; + } + } + // Method _createMessageAAD moved to constructor area for early availability + /** + * Validate message AAD with sequence number + * This ensures message integrity and prevents replay attacks + */ + _validateMessageAAD(aadString, expectedMessageType = null) { + try { + const aad = JSON.parse(aadString); + if (aad.sessionId !== (this.currentSession?.sessionId || "unknown")) { + throw new Error("AAD sessionId mismatch - possible replay attack"); + } + if (aad.keyFingerprint !== (this.keyFingerprint || "unknown")) { + throw new Error("AAD keyFingerprint mismatch - possible key substitution attack"); + } + if (!this._validateIncomingSequenceNumber(aad.sequenceNumber, aad.messageType)) { + throw new Error("Sequence number validation failed - possible replay or DoS attack"); + } + if (expectedMessageType && aad.messageType !== expectedMessageType) { + throw new Error(`AAD messageType mismatch - expected ${expectedMessageType}, got ${aad.messageType}`); + } + return aad; + } catch (error) { + this._secureLog("error", "AAD validation failed", { error: error.message, aadString }); + throw new Error(`AAD validation failed: ${error.message}`); + } + } + /** + * Get anti-replay protection status + * This shows the current state of replay protection + */ + getAntiReplayStatus() { + const status = { + replayProtectionEnabled: this.replayProtectionEnabled, + replayWindowSize: this.replayWindowSize, + currentReplayWindowSize: this.replayWindow.size, + sequenceNumber: this.sequenceNumber, + expectedSequenceNumber: this.expectedSequenceNumber, + maxSequenceGap: this.maxSequenceGap, + replayWindowEntries: Array.from(this.replayWindow).sort((a, b) => a - b) + }; + this._secureLog("info", "Anti-replay status retrieved", status); + return status; + } + /** + * Configure anti-replay protection + * This allows fine-tuning of replay protection parameters + */ + configureAntiReplayProtection(config) { + try { + if (config.windowSize !== void 0) { + if (config.windowSize < 16 || config.windowSize > 1024) { + throw new Error("Replay window size must be between 16 and 1024"); + } + this.replayWindowSize = config.windowSize; + } + if (config.maxGap !== void 0) { + if (config.maxGap < 10 || config.maxGap > 1e3) { + throw new Error("Max sequence gap must be between 10 and 1000"); + } + this.maxSequenceGap = config.maxGap; + } + if (config.enabled !== void 0) { + this.replayProtectionEnabled = config.enabled; + } + this._secureLog("info", "Anti-replay protection configured", config); + return true; + } catch (error) { + this._secureLog("error", "Failed to configure anti-replay protection", { error: error.message }); + return false; + } + } +}; + +// src/session/PayPerSessionManager.js +var PayPerSessionManager = class { + constructor(config = {}) { + this.sessionPrices = { + demo: { sats: 0, hours: 0.1, usd: 0, securityLevel: "basic" }, + basic: { sats: 5e3, hours: 1, usd: 2, securityLevel: "enhanced" }, + premium: { sats: 2e4, hours: 6, usd: 8, securityLevel: "maximum" } + }; + this.currentSession = null; + this.sessionTimer = null; + this.onSessionExpired = null; + this.staticLightningAddress = "dullpastry62@walletofsatoshi.com"; + this.usedPreimages = /* @__PURE__ */ new Set(); + this.preimageCleanupInterval = null; + this.demoSessions = /* @__PURE__ */ new Map(); + this.maxDemoSessionsPerUser = 3; + this.demoCooldownPeriod = 24 * 60 * 60 * 1e3; + this.demoSessionCooldown = 1 * 60 * 1e3; + this.demoSessionMaxDuration = 6 * 60 * 1e3; + this.activeDemoSessions = /* @__PURE__ */ new Set(); + this.maxGlobalDemoSessions = 10; + this.completedDemoSessions = /* @__PURE__ */ new Map(); + this.minTimeBetweenCompletedSessions = 15 * 60 * 1e3; + this.minimumPaymentSats = 1e3; + this.verificationConfig = { + method: config.method || "lnbits", + apiUrl: config.apiUrl || "https://demo.lnbits.com", + apiKey: config.apiKey || "a7226682253f4dd7bdb2d9487a9a59f8", + walletId: config.walletId || "649903697b03457d8b12c4eae7b2fab9", + isDemo: config.isDemo !== void 0 ? config.isDemo : true, + demoTimeout: 3e4, + retryAttempts: 3, + invoiceExpiryMinutes: 15 + }; + this.lastApiCall = 0; + this.apiCallMinInterval = 1e3; + this.startPreimageCleanup(); + this.startDemoSessionCleanup(); + this.startActiveDemoSessionCleanup(); + this.globalDemoCounter = 0; + this.memoryStorage = /* @__PURE__ */ new Map(); + this.currentTabId = null; + this.tabHeartbeatInterval = null; + this.initializePersistentStorage(); + this.performEnhancedCleanup(); + const multiTabCheck = this.checkMultiTabProtection(); + if (!multiTabCheck.allowed) { + console.warn("\u274C Multi-tab protection triggered:", multiTabCheck.message); + } + console.log("\u{1F4B0} PayPerSessionManager initialized with TIERED security levels"); + setInterval(() => { + this.savePersistentData(); + }, 3e4); + this.notifySecurityUpdate = () => { + document.dispatchEvent(new CustomEvent("security-level-updated", { + detail: { timestamp: Date.now(), manager: "webrtc" } + })); + }; + console.log("\u{1F4B0} PayPerSessionManager initialized with ENHANCED secure demo mode and auto-save"); + } + getSecurityLevelForSession(sessionType) { + const pricing = this.sessionPrices[sessionType]; + if (!pricing) return "basic"; + return pricing.securityLevel || "basic"; + } + // Check if the function is allowed for the given session type + isFeatureAllowedForSession(sessionType, feature) { + const securityLevel = this.getSecurityLevelForSession(sessionType); + const featureMatrix = { + "basic": { + // DEMO сессии - только базовые функции + hasEncryption: true, + hasECDH: true, + hasECDSA: false, + hasMutualAuth: false, + hasMetadataProtection: false, + hasEnhancedReplayProtection: false, + hasNonExtractableKeys: false, + hasRateLimiting: true, + hasEnhancedValidation: false, + hasPFS: false, + // Advanced features are DISABLED for demo + hasNestedEncryption: false, + hasPacketPadding: false, + hasPacketReordering: false, + hasAntiFingerprinting: false, + hasFakeTraffic: false, + hasDecoyChannels: false, + hasMessageChunking: false + }, + "enhanced": { + // BASIC paid sessions - improved security + hasEncryption: true, + hasECDH: true, + hasECDSA: true, + hasMutualAuth: true, + hasMetadataProtection: true, + hasEnhancedReplayProtection: true, + hasNonExtractableKeys: true, + hasRateLimiting: true, + hasEnhancedValidation: true, + hasPFS: true, + // Partially enabled advanced features + hasNestedEncryption: true, + hasPacketPadding: true, + hasPacketReordering: false, + hasAntiFingerprinting: false, + hasFakeTraffic: false, + hasDecoyChannels: false, + hasMessageChunking: false + }, + "maximum": { + // PREMIUM sessions - all functions included + hasEncryption: true, + hasECDH: true, + hasECDSA: true, + hasMutualAuth: true, + hasMetadataProtection: true, + hasEnhancedReplayProtection: true, + hasNonExtractableKeys: true, + hasRateLimiting: true, + hasEnhancedValidation: true, + hasPFS: true, + // ALL advanced features + hasNestedEncryption: true, + hasPacketPadding: true, + hasPacketReordering: true, + hasAntiFingerprinting: true, + hasFakeTraffic: true, + hasDecoyChannels: true, + hasMessageChunking: true + } + }; + return featureMatrix[securityLevel]?.[feature] || false; + } + // ============================================ + // FIXED DEMO MODE: Improved controls and management + // ============================================ + startActiveDemoSessionCleanup() { + setInterval(() => { + const now = Date.now(); + let cleanedCount = 0; + for (const preimage of this.activeDemoSessions) { + const demoTimestamp = this.extractDemoTimestamp(preimage); + if (demoTimestamp && now - demoTimestamp > this.demoSessionMaxDuration) { + this.activeDemoSessions.delete(preimage); + cleanedCount++; + } + } + if (cleanedCount > 0) { + console.log(`\u{1F9F9} Cleaned ${cleanedCount} expired active demo sessions`); + } + }, 3e4); + } + startDemoSessionCleanup() { + setInterval(() => { + const now = Date.now(); + const maxAge = 25 * 60 * 60 * 1e3; + let cleanedCount = 0; + for (const [identifier, data] of this.demoSessions.entries()) { + if (now - data.lastUsed > maxAge) { + this.demoSessions.delete(identifier); + cleanedCount++; + } + if (data.sessions) { + const originalCount = data.sessions.length; + data.sessions = data.sessions.filter( + (session) => now - session.timestamp < maxAge + ); + if (data.sessions.length === 0 && now - data.lastUsed > maxAge) { + this.demoSessions.delete(identifier); + cleanedCount++; + } + } + } + for (const [identifier, sessions] of this.completedDemoSessions.entries()) { + const filteredSessions = sessions.filter( + (session) => now - session.endTime < maxAge + ); + if (filteredSessions.length === 0) { + this.completedDemoSessions.delete(identifier); + } else { + this.completedDemoSessions.set(identifier, filteredSessions); + } + } + if (cleanedCount > 0) { + console.log(`\u{1F9F9} Cleaned ${cleanedCount} old demo session records`); + } + }, 60 * 60 * 1e3); + } + // IMPROVED user fingerprint generation + generateAdvancedUserFingerprint() { + try { + const basicComponents = [ + navigator.userAgent || "", + navigator.language || "", + screen.width + "x" + screen.height, + Intl.DateTimeFormat().resolvedOptions().timeZone || "", + navigator.hardwareConcurrency || 0, + navigator.deviceMemory || 0, + navigator.platform || "", + navigator.cookieEnabled ? "1" : "0", + window.screen.colorDepth || 0, + window.screen.pixelDepth || 0, + navigator.maxTouchPoints || 0, + navigator.onLine ? "1" : "0" + ]; + const hardwareComponents = []; + try { + const canvas = document.createElement("canvas"); + const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); + if (gl) { + const debugInfo = gl.getExtension("WEBGL_debug_renderer_info"); + if (debugInfo) { + hardwareComponents.push(gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || ""); + hardwareComponents.push(gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || ""); + } + hardwareComponents.push(gl.getParameter(gl.VERSION) || ""); + hardwareComponents.push(gl.getParameter(gl.SHADING_LANGUAGE_VERSION) || ""); + } + } catch (e) { + hardwareComponents.push("webgl_error"); + } + try { + const canvas = document.createElement("canvas"); + canvas.width = 200; + canvas.height = 50; + const ctx = canvas.getContext("2d"); + ctx.textBaseline = "top"; + ctx.font = "14px Arial"; + ctx.fillText("SecureBit Demo Fingerprint \u{1F512}", 2, 2); + ctx.fillStyle = "rgba(255,0,0,0.5)"; + ctx.fillRect(50, 10, 20, 20); + hardwareComponents.push(canvas.toDataURL()); + } catch (e) { + hardwareComponents.push("canvas_error"); + } + try { + const audioContext = new (window.AudioContext || window.webkitAudioContext)(); + const oscillator = audioContext.createOscillator(); + const analyser = audioContext.createAnalyser(); + const gain = audioContext.createGain(); + oscillator.connect(analyser); + analyser.connect(gain); + gain.connect(audioContext.destination); + oscillator.frequency.setValueAtTime(1e3, audioContext.currentTime); + gain.gain.setValueAtTime(0, audioContext.currentTime); + hardwareComponents.push(audioContext.sampleRate.toString()); + hardwareComponents.push(audioContext.state); + hardwareComponents.push(analyser.frequencyBinCount.toString()); + audioContext.close(); + } catch (e) { + hardwareComponents.push("audio_error"); + } + const cpuBenchmark = this.performCPUBenchmark(); + hardwareComponents.push(cpuBenchmark); + const allComponents = [...basicComponents, ...hardwareComponents]; + let primaryHash = 0; + let secondaryHash = 0; + let tertiaryHash = 0; + const primaryStr = allComponents.slice(0, 8).join("|"); + const secondaryStr = allComponents.slice(8, 16).join("|"); + const tertiaryStr = allComponents.slice(16).join("|"); + for (let i = 0; i < primaryStr.length; i++) { + const char = primaryStr.charCodeAt(i); + primaryHash = (primaryHash << 7) - primaryHash + char; + primaryHash = primaryHash & primaryHash; + } + for (let i = 0; i < secondaryStr.length; i++) { + const char = secondaryStr.charCodeAt(i); + secondaryHash = (secondaryHash << 11) - secondaryHash + char; + secondaryHash = secondaryHash & secondaryHash; + } + for (let i = 0; i < tertiaryStr.length; i++) { + const char = tertiaryStr.charCodeAt(i); + tertiaryHash = (tertiaryHash << 13) - tertiaryHash + char; + tertiaryHash = tertiaryHash & tertiaryHash; + } + const combined = `${Math.abs(primaryHash).toString(36)}_${Math.abs(secondaryHash).toString(36)}_${Math.abs(tertiaryHash).toString(36)}`; + console.log("\u{1F512} Enhanced fingerprint generated:", { + components: allComponents.length, + primaryLength: primaryStr.length, + secondaryLength: secondaryStr.length, + tertiaryLength: tertiaryStr.length, + fingerprintLength: combined.length + }); + return combined; + } catch (error) { + console.warn("Failed to generate enhanced fingerprint:", error); + return "fallback_" + Date.now().toString(36) + "_" + Math.random().toString(36).substr(2, 9); + } + } + performCPUBenchmark() { + const start2 = performance.now(); + let result = 0; + for (let i = 0; i < 1e5; i++) { + result += Math.sin(i) * Math.cos(i); + } + const end = performance.now(); + const duration = Math.round(end - start2); + if (duration < 5) return "fast_cpu"; + if (duration < 15) return "medium_cpu"; + if (duration < 30) return "slow_cpu"; + return "very_slow_cpu"; + } + initializePersistentStorage() { + this.storageKeys = { + demoSessions: "sb_demo_sessions_v2", + completedSessions: "sb_completed_sessions_v2", + globalCounter: "sb_global_demo_counter_v2", + lastCleanup: "sb_last_cleanup_v2", + hardwareFingerprint: "sb_hw_fingerprint_v2" + }; + this.loadPersistentData(); + } + loadPersistentData() { + try { + const savedDemoSessions = this.getFromStorage(this.storageKeys.demoSessions); + if (savedDemoSessions) { + const parsed = JSON.parse(savedDemoSessions); + for (const [key, value] of Object.entries(parsed)) { + this.demoSessions.set(key, value); + } + } + const savedCompletedSessions = this.getFromStorage(this.storageKeys.completedSessions); + if (savedCompletedSessions) { + const parsed = JSON.parse(savedCompletedSessions); + for (const [key, value] of Object.entries(parsed)) { + this.completedDemoSessions.set(key, value); + } + } + const savedGlobalCounter = this.getFromStorage(this.storageKeys.globalCounter); + if (savedGlobalCounter) { + this.globalDemoCounter = parseInt(savedGlobalCounter) || 0; + } else { + this.globalDemoCounter = 0; + } + console.log("\u{1F4CA} Persistent data loaded:", { + demoSessions: this.demoSessions.size, + completedSessions: this.completedDemoSessions.size, + globalCounter: this.globalDemoCounter + }); + } catch (error) { + console.warn("Failed to load persistent data:", error); + this.globalDemoCounter = 0; + } + } + savePersistentData() { + try { + const demoSessionsObj = Object.fromEntries(this.demoSessions); + this.setToStorage(this.storageKeys.demoSessions, JSON.stringify(demoSessionsObj)); + const completedSessionsObj = Object.fromEntries(this.completedDemoSessions); + this.setToStorage(this.storageKeys.completedSessions, JSON.stringify(completedSessionsObj)); + this.setToStorage(this.storageKeys.globalCounter, this.globalDemoCounter.toString()); + this.setToStorage(this.storageKeys.lastCleanup, Date.now().toString()); + } catch (error) { + console.warn("Failed to save persistent data:", error); + } + } + getFromStorage(key) { + try { + if (typeof localStorage !== "undefined") { + const value = localStorage.getItem(key); + if (value) return value; + } + } catch (e) { + } + try { + if (typeof sessionStorage !== "undefined") { + const value = sessionStorage.getItem(key); + if (value) return value; + } + } catch (e) { + } + try { + if ("caches" in window) { + } + } catch (e) { + } + return null; + } + setToStorage(key, value) { + try { + if (typeof localStorage !== "undefined") { + localStorage.setItem(key, value); + } + } catch (e) { + } + try { + if (typeof sessionStorage !== "undefined") { + sessionStorage.setItem(key, value); + } + } catch (e) { + } + if (!this.memoryStorage) this.memoryStorage = /* @__PURE__ */ new Map(); + this.memoryStorage.set(key, value); + } + checkAntiResetProtection(userFingerprint) { + if (!this.globalDemoCounter) { + this.globalDemoCounter = 0; + } + const hardwareFingerprint = this.getHardwareFingerprint(); + const savedHardwareFingerprint = this.getFromStorage(this.storageKeys.hardwareFingerprint); + if (savedHardwareFingerprint && savedHardwareFingerprint !== hardwareFingerprint) { + console.warn("\u{1F6A8} Hardware fingerprint mismatch detected - possible reset attempt"); + this.globalDemoCounter += 5; + this.savePersistentData(); + return { + isValid: false, + reason: "hardware_mismatch", + penalty: 5 + }; + } + this.setToStorage(this.storageKeys.hardwareFingerprint, hardwareFingerprint); + if (this.globalDemoCounter >= 10) { + return { + isValid: false, + reason: "global_limit_exceeded", + globalCount: this.globalDemoCounter + }; + } + return { + isValid: true, + globalCount: this.globalDemoCounter + }; + } + getHardwareFingerprint() { + const components = []; + components.push(navigator.hardwareConcurrency || 0); + components.push(navigator.deviceMemory || 0); + try { + const canvas = document.createElement("canvas"); + const gl = canvas.getContext("webgl"); + if (gl) { + const debugInfo = gl.getExtension("WEBGL_debug_renderer_info"); + if (debugInfo) { + components.push(gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || ""); + components.push(gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || ""); + } + } + } catch (e) { + components.push("webgl_unavailable"); + } + components.push(screen.width); + components.push(screen.height); + components.push(screen.colorDepth); + components.push(Intl.DateTimeFormat().resolvedOptions().timeZone); + let hash = 0; + const str = components.join("|"); + for (let i = 0; i < str.length; i++) { + const char = str.charCodeAt(i); + hash = (hash << 5) - hash + char; + hash = hash & hash; + } + return Math.abs(hash).toString(36); + } + registerEnhancedDemoSessionUsage(userFingerprint, preimage) { + const session = this.registerDemoSessionUsage(userFingerprint, preimage); + this.savePersistentData(); + console.log("\u{1F4CA} Enhanced demo session registered:", { + userFingerprint: userFingerprint.substring(0, 12), + globalCount: this.globalDemoCounter, + sessionId: session.sessionId, + timestamp: (/* @__PURE__ */ new Date()).toISOString() + }); + return session; + } + // COMPLETELY REWRITTEN demo session limits check + checkEnhancedDemoSessionLimits(userFingerprint) { + const antiResetCheck = this.checkAntiResetProtection(userFingerprint); + if (!antiResetCheck.isValid) { + return { + allowed: false, + reason: antiResetCheck.reason, + message: this.getAntiResetMessage(antiResetCheck), + globalCount: antiResetCheck.globalCount, + penalty: antiResetCheck.penalty + }; + } + const regularCheck = this.checkDemoSessionLimits(userFingerprint); + if (regularCheck.allowed) { + this.globalDemoCounter++; + this.savePersistentData(); + } + return { + ...regularCheck, + globalCount: this.globalDemoCounter + }; + } + getAntiResetMessage(antiResetCheck) { + switch (antiResetCheck.reason) { + case "hardware_mismatch": + return "An attempt to reset restrictions was detected. Access to demo mode is temporarily restricted."; + case "global_limit_exceeded": + return `Global demo session limit exceeded (${antiResetCheck.globalCount}/10). A paid session is required to continue.`; + default: + return "Access to demo mode is restricted for security reasons."; + } + } + // FIXED demo session usage registration + registerDemoSessionUsage(userFingerprint, preimage) { + const now = Date.now(); + const userData = this.demoSessions.get(userFingerprint) || { + count: 0, + lastUsed: 0, + sessions: [], + firstUsed: now + }; + userData.count++; + userData.lastUsed = now; + const newSession = { + timestamp: now, + sessionId: crypto.getRandomValues(new Uint32Array(1))[0].toString(36), + duration: this.demoSessionMaxDuration, + preimage, + status: "active" + }; + userData.sessions.push(newSession); + userData.sessions = userData.sessions.filter( + (session) => now - session.timestamp < this.demoCooldownPeriod + ); + this.activeDemoSessions.add(preimage); + this.demoSessions.set(userFingerprint, userData); + console.log(`\u{1F4CA} Demo session registered for user ${userFingerprint.substring(0, 12)} (${userData.sessions.length}/${this.maxDemoSessionsPerUser} today)`); + console.log(`\u{1F310} Global active demo sessions: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`); + return newSession; + } + performEnhancedCleanup() { + const now = Date.now(); + const lastCleanup = parseInt(this.getFromStorage(this.storageKeys.lastCleanup)) || 0; + if (now - lastCleanup < 6 * 60 * 60 * 1e3) { + return; + } + console.log("\u{1F9F9} Performing enhanced cleanup..."); + const maxAge = 25 * 60 * 60 * 1e3; + let cleanedSessions = 0; + for (const [identifier, data] of this.demoSessions.entries()) { + if (now - data.lastUsed > maxAge) { + this.demoSessions.delete(identifier); + cleanedSessions++; + } + } + let cleanedCompleted = 0; + for (const [identifier, sessions] of this.completedDemoSessions.entries()) { + const filteredSessions = sessions.filter( + (session) => now - session.endTime < maxAge + ); + if (filteredSessions.length === 0) { + this.completedDemoSessions.delete(identifier); + cleanedCompleted++; + } else { + this.completedDemoSessions.set(identifier, filteredSessions); + } + } + const weekAgo = 7 * 24 * 60 * 60 * 1e3; + if (now - lastCleanup > weekAgo) { + this.globalDemoCounter = Math.max(0, this.globalDemoCounter - 3); + console.log("\u{1F504} Global demo counter reset (weekly):", this.globalDemoCounter); + } + this.savePersistentData(); + console.log("\u2705 Enhanced cleanup completed:", { + cleanedSessions, + cleanedCompleted, + globalCounter: this.globalDemoCounter + }); + } + checkMultiTabProtection() { + const tabId = "tab_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9); + const activeTabsKey = "sb_active_tabs"; + try { + const activeTabsStr = this.getFromStorage(activeTabsKey); + const activeTabs = activeTabsStr ? JSON.parse(activeTabsStr) : []; + const now = Date.now(); + const validTabs = activeTabs.filter((tab) => now - tab.timestamp < 3e4); + if (validTabs.length >= 2) { + return { + allowed: false, + reason: "multiple_tabs", + message: "Demo mode is only available in one tab at a time.." + }; + } + validTabs.push({ + tabId, + timestamp: now + }); + this.setToStorage(activeTabsKey, JSON.stringify(validTabs)); + this.currentTabId = tabId; + this.startTabHeartbeat(); + return { + allowed: true, + tabId + }; + } catch (error) { + console.warn("Multi-tab protection error:", error); + return { allowed: true }; + } + } + startTabHeartbeat() { + if (this.tabHeartbeatInterval) { + clearInterval(this.tabHeartbeatInterval); + } + this.tabHeartbeatInterval = setInterval(() => { + this.updateTabHeartbeat(); + }, 1e4); + } + updateTabHeartbeat() { + if (!this.currentTabId) return; + try { + const activeTabsKey = "sb_active_tabs"; + const activeTabsStr = this.getFromStorage(activeTabsKey); + const activeTabs = activeTabsStr ? JSON.parse(activeTabsStr) : []; + const updatedTabs = activeTabs.map((tab) => { + if (tab.tabId === this.currentTabId) { + return { + ...tab, + timestamp: Date.now() + }; + } + return tab; + }); + this.setToStorage(activeTabsKey, JSON.stringify(updatedTabs)); + } catch (error) { + console.warn("Tab heartbeat update failed:", error); + } + } + // NEW method: Register demo session completion + registerDemoSessionCompletion(userFingerprint, sessionDuration, preimage) { + const now = Date.now(); + if (preimage) { + this.activeDemoSessions.delete(preimage); + } + const completedSessions = this.completedDemoSessions.get(userFingerprint) || []; + completedSessions.push({ + endTime: now, + duration: sessionDuration, + preimage: preimage ? preimage.substring(0, 16) + "..." : "unknown" + // Логируем только часть для безопасности + }); + const filteredSessions = completedSessions.filter((session) => now - session.endTime < this.minTimeBetweenCompletedSessions).slice(-5); + this.completedDemoSessions.set(userFingerprint, filteredSessions); + const userData = this.demoSessions.get(userFingerprint); + if (userData && userData.sessions) { + const session = userData.sessions.find((s) => s.preimage === preimage); + if (session) { + session.status = "completed"; + session.endTime = now; + } + } + console.log(`\u2705 Demo session completed for user ${userFingerprint.substring(0, 12)}`); + console.log(`\u{1F310} Global active demo sessions: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`); + } + // ENHANCED demo preimage generation with additional protection + generateSecureDemoPreimage() { + try { + const timestamp = Date.now(); + const randomBytes = crypto.getRandomValues(new Uint8Array(24)); + const timestampBytes = new Uint8Array(4); + const versionBytes = new Uint8Array(4); + const timestampSeconds = Math.floor(timestamp / 1e3); + timestampBytes[0] = timestampSeconds >>> 24 & 255; + timestampBytes[1] = timestampSeconds >>> 16 & 255; + timestampBytes[2] = timestampSeconds >>> 8 & 255; + timestampBytes[3] = timestampSeconds & 255; + versionBytes[0] = 222; + versionBytes[1] = 224; + versionBytes[2] = 0; + versionBytes[3] = 2; + const combined = new Uint8Array(32); + combined.set(versionBytes, 0); + combined.set(timestampBytes, 4); + combined.set(randomBytes, 8); + const preimage = Array.from(combined).map((b) => b.toString(16).padStart(2, "0")).join(""); + console.log(`\u{1F3AE} Generated SECURE demo preimage v2: ${preimage.substring(0, 16)}...`); + return preimage; + } catch (error) { + console.error("Failed to generate demo preimage:", error); + throw new Error("Failed to generate secure demo preimage"); + } + } + // UPDATED demo preimage check + isDemoPreimage(preimage) { + if (!preimage || typeof preimage !== "string" || preimage.length !== 64) { + return false; + } + const lower = preimage.toLowerCase(); + return lower.startsWith("dee00001") || lower.startsWith("dee00002"); + } + // Extract timestamp from demo preimage + extractDemoTimestamp(preimage) { + if (!this.isDemoPreimage(preimage)) { + return null; + } + try { + const timestampHex = preimage.slice(8, 16); + const timestampSeconds = parseInt(timestampHex, 16); + return timestampSeconds * 1e3; + } catch (error) { + console.error("Failed to extract demo timestamp:", error); + return null; + } + } + // ============================================ + // VALIDATION AND CHECKS + // ============================================ + validateSessionType(sessionType) { + if (!sessionType || typeof sessionType !== "string") { + throw new Error("Session type must be a non-empty string"); + } + if (!this.sessionPrices[sessionType]) { + throw new Error(`Invalid session type: ${sessionType}. Allowed: ${Object.keys(this.sessionPrices).join(", ")}`); + } + const pricing = this.sessionPrices[sessionType]; + if (sessionType === "demo") { + return true; + } + if (pricing.sats < this.minimumPaymentSats) { + throw new Error(`Session type ${sessionType} below minimum payment threshold (${this.minimumPaymentSats} sats)`); + } + return true; + } + calculateEntropy(str) { + const freq = {}; + for (let char of str) { + freq[char] = (freq[char] || 0) + 1; + } + let entropy = 0; + const length = str.length; + for (let char in freq) { + const p = freq[char] / length; + entropy -= p * Math.log2(p); + } + return entropy; + } + // ============================================ + // ENHANCED verification with additional checks + // ============================================ + async verifyCryptographically(preimage, paymentHash) { + try { + if (!preimage || typeof preimage !== "string" || preimage.length !== 64) { + throw new Error("Invalid preimage format"); + } + if (!/^[0-9a-fA-F]{64}$/.test(preimage)) { + throw new Error("Preimage must be valid hexadecimal"); + } + if (this.isDemoPreimage(preimage)) { + console.log("\u{1F3AE} Demo preimage detected - performing ENHANCED validation..."); + if (this.usedPreimages.has(preimage)) { + throw new Error("Demo preimage already used - replay attack prevented"); + } + if (this.activeDemoSessions.has(preimage)) { + throw new Error("Demo preimage already active - concurrent usage prevented"); + } + const demoTimestamp = this.extractDemoTimestamp(preimage); + if (!demoTimestamp) { + throw new Error("Invalid demo preimage timestamp"); + } + const now = Date.now(); + const age = now - demoTimestamp; + if (age > 15 * 60 * 1e3) { + throw new Error(`Demo preimage expired (age: ${Math.round(age / (60 * 1e3))} minutes)`); + } + if (age < -2 * 60 * 1e3) { + throw new Error("Demo preimage timestamp from future - possible clock manipulation"); + } + const userFingerprint = this.generateAdvancedUserFingerprint(); + const limitsCheck = this.checkEnhancedDemoSessionLimits(userFingerprint); + if (!limitsCheck.allowed) { + throw new Error(`Demo session limits exceeded: ${limitsCheck.message}`); + } + this.registerEnhancedDemoSessionUsage(userFingerprint, preimage); + console.log("\u2705 Demo preimage ENHANCED validation passed"); + return true; + } + if (this.usedPreimages.has(preimage)) { + throw new Error("Preimage already used - replay attack prevented"); + } + const entropy = this.calculateEntropy(preimage); + if (entropy < 3.5) { + throw new Error(`Preimage has insufficient entropy: ${entropy.toFixed(2)}`); + } + const preimageBytes = new Uint8Array(preimage.match(/.{2}/g).map((byte) => parseInt(byte, 16))); + const hashBuffer = await crypto.subtle.digest("SHA-256", preimageBytes); + const computedHash = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join(""); + const isValid = computedHash === paymentHash.toLowerCase(); + if (isValid) { + this.usedPreimages.add(preimage); + console.log("\u2705 Standard preimage cryptographic validation passed"); + } + return isValid; + } catch (error) { + console.error("\u274C Cryptographic verification failed:", error.message); + return false; + } + } + // ============================================ + // LIGHTNING NETWORK INTEGRATION + // ============================================ + // Creating a Lightning invoice + async createLightningInvoice(sessionType) { + const pricing = this.sessionPrices[sessionType]; + if (!pricing) throw new Error("Invalid session type"); + try { + console.log(`Creating ${sessionType} invoice for ${pricing.sats} sats...`); + const now = Date.now(); + if (now - this.lastApiCall < this.apiCallMinInterval) { + throw new Error("API rate limit: please wait before next request"); + } + this.lastApiCall = now; + const healthCheck = await fetch(`${this.verificationConfig.apiUrl}/api/v1/health`, { + method: "GET", + headers: { + "X-Api-Key": this.verificationConfig.apiKey + }, + signal: AbortSignal.timeout(5e3) + }); + if (!healthCheck.ok) { + throw new Error(`LNbits API unavailable: ${healthCheck.status}`); + } + const response = await fetch(`${this.verificationConfig.apiUrl}/api/v1/payments`, { + method: "POST", + headers: { + "X-Api-Key": this.verificationConfig.apiKey, + "Content-Type": "application/json" + }, + body: JSON.stringify({ + out: false, + amount: pricing.sats, + memo: `SecureBit.chat ${sessionType} session (${pricing.hours}h) - ${Date.now()}`, + unit: "sat", + expiry: this.verificationConfig.invoiceExpiryMinutes * 60 + }), + signal: AbortSignal.timeout(1e4) + }); + if (!response.ok) { + const errorText = await response.text(); + console.error("LNbits API error response:", errorText); + throw new Error(`LNbits API error ${response.status}: ${errorText}`); + } + const data = await response.json(); + console.log("\u2705 Lightning invoice created successfully"); + return { + paymentRequest: data.bolt11 || data.payment_request, + paymentHash: data.payment_hash, + checkingId: data.checking_id || data.payment_hash, + amount: data.amount || pricing.sats, + sessionType, + createdAt: Date.now(), + expiresAt: Date.now() + this.verificationConfig.invoiceExpiryMinutes * 60 * 1e3, + description: data.description || data.memo || `SecureBit.chat ${sessionType} session`, + bolt11: data.bolt11 || data.payment_request, + memo: data.memo || `SecureBit.chat ${sessionType} session` + }; + } catch (error) { + console.error("\u274C Lightning invoice creation failed:", error); + if (this.verificationConfig.isDemo && error.message.includes("API")) { + console.log("\u{1F504} Creating demo invoice for testing..."); + return this.createDemoInvoice(sessionType); + } + throw error; + } + } + // Creating a demo invoice for testing + createDemoInvoice(sessionType) { + const pricing = this.sessionPrices[sessionType]; + const demoHash = Array.from(crypto.getRandomValues(new Uint8Array(32))).map((b) => b.toString(16).padStart(2, "0")).join(""); + return { + paymentRequest: `lntb${pricing.sats}1p${demoHash.substring(0, 16)}...`, + paymentHash: demoHash, + checkingId: demoHash, + amount: pricing.sats, + sessionType, + createdAt: Date.now(), + expiresAt: Date.now() + 5 * 60 * 1e3, + description: `SecureBit.chat ${sessionType} session (DEMO)`, + isDemo: true + }; + } + // Checking payment status via LNbits + async checkPaymentStatus(checkingId) { + try { + console.log(`\u{1F50D} Checking payment status for: ${checkingId?.substring(0, 8)}...`); + const now = Date.now(); + if (now - this.lastApiCall < this.apiCallMinInterval) { + throw new Error("API rate limit exceeded"); + } + this.lastApiCall = now; + const response = await fetch(`${this.verificationConfig.apiUrl}/api/v1/payments/${checkingId}`, { + method: "GET", + headers: { + "X-Api-Key": this.verificationConfig.apiKey, + "Content-Type": "application/json" + }, + signal: AbortSignal.timeout(1e4) + }); + if (!response.ok) { + const errorText = await response.text(); + console.error("Payment status check failed:", errorText); + throw new Error(`Payment check failed: ${response.status} - ${errorText}`); + } + const data = await response.json(); + console.log("\u{1F4CA} Payment status retrieved successfully"); + return { + paid: data.paid || false, + preimage: data.preimage || null, + details: data.details || {}, + amount: data.amount || 0, + fee: data.fee || 0, + timestamp: data.timestamp || Date.now(), + bolt11: data.bolt11 || null + }; + } catch (error) { + console.error("\u274C Payment status check error:", error); + if (this.verificationConfig.isDemo && error.message.includes("API")) { + console.log("\u{1F504} Returning demo payment status..."); + return { + paid: false, + preimage: null, + details: { demo: true }, + amount: 0, + fee: 0, + timestamp: Date.now() + }; + } + throw error; + } + } + // Payment verification via LNbits API + async verifyPaymentLNbits(preimage, paymentHash) { + try { + console.log(`\u{1F510} Verifying payment via LNbits API...`); + if (!this.verificationConfig.apiUrl || !this.verificationConfig.apiKey) { + throw new Error("LNbits API configuration missing"); + } + const now = Date.now(); + if (now - this.lastApiCall < this.apiCallMinInterval) { + throw new Error("API rate limit: please wait before next verification"); + } + this.lastApiCall = now; + const response = await fetch(`${this.verificationConfig.apiUrl}/api/v1/payments/${paymentHash}`, { + method: "GET", + headers: { + "X-Api-Key": this.verificationConfig.apiKey, + "Content-Type": "application/json" + }, + signal: AbortSignal.timeout(1e4) + }); + if (!response.ok) { + const errorText = await response.text(); + console.error("LNbits verification failed:", errorText); + throw new Error(`API request failed: ${response.status} - ${errorText}`); + } + const paymentData = await response.json(); + console.log("\u{1F4CB} Payment verification data received from LNbits"); + const isPaid = paymentData.paid === true; + const preimageMatches = paymentData.preimage === preimage; + const amountValid = paymentData.amount >= this.minimumPaymentSats; + const paymentTimestamp = paymentData.timestamp || paymentData.time || 0; + const paymentAge = now - paymentTimestamp * 1e3; + const maxPaymentAge = 24 * 60 * 60 * 1e3; + if (paymentAge > maxPaymentAge && paymentTimestamp > 0) { + throw new Error(`Payment too old: ${Math.round(paymentAge / (60 * 60 * 1e3))} hours (max: 24h)`); + } + if (isPaid && preimageMatches && amountValid) { + console.log("\u2705 Payment verified successfully via LNbits"); + return { + verified: true, + amount: paymentData.amount, + fee: paymentData.fee || 0, + timestamp: paymentTimestamp || now, + method: "lnbits", + verificationTime: now, + paymentAge + }; + } + console.log("\u274C LNbits payment verification failed:", { + paid: isPaid, + preimageMatch: preimageMatches, + amountValid, + paymentAge: Math.round(paymentAge / (60 * 1e3)) + " minutes" + }); + return { + verified: false, + reason: "Payment verification failed: not paid, preimage mismatch, insufficient amount, or payment too old", + method: "lnbits", + details: { + paid: isPaid, + preimageMatch: preimageMatches, + amountValid, + paymentAge + } + }; + } catch (error) { + console.error("\u274C LNbits payment verification failed:", error); + return { + verified: false, + reason: error.message, + method: "lnbits", + error: true + }; + } + } + // ============================================ + // BASIC LOGIC OF PAYMENT VERIFICATION + // ============================================ + // The main method of payment verification + async verifyPayment(preimage, paymentHash) { + console.log(`\u{1F510} Starting payment verification...`); + try { + if (!preimage || !paymentHash) { + throw new Error("Missing preimage or payment hash"); + } + if (typeof preimage !== "string" || typeof paymentHash !== "string") { + throw new Error("Preimage and payment hash must be strings"); + } + if (this.isDemoPreimage(preimage)) { + console.log("\u{1F3AE} Processing demo session verification..."); + const cryptoValid2 = await this.verifyCryptographically(preimage, paymentHash); + if (!cryptoValid2) { + return { + verified: false, + reason: "Demo preimage verification failed", + stage: "crypto" + }; + } + console.log("\u2705 Demo session verified successfully"); + return { + verified: true, + method: "demo", + sessionType: "demo", + isDemo: true, + warning: "Demo session - limited duration (6 minutes)" + }; + } + const cryptoValid = await this.verifyCryptographically(preimage, paymentHash); + if (!cryptoValid) { + return { + verified: false, + reason: "Cryptographic verification failed", + stage: "crypto" + }; + } + console.log("\u2705 Cryptographic verification passed"); + if (!this.verificationConfig.isDemo) { + switch (this.verificationConfig.method) { + case "lnbits": + const lnbitsResult = await this.verifyPaymentLNbits(preimage, paymentHash); + if (!lnbitsResult.verified) { + return { + verified: false, + reason: lnbitsResult.reason || "LNbits verification failed", + stage: "lightning", + details: lnbitsResult.details + }; + } + return lnbitsResult; + default: + console.warn("Unknown verification method, using crypto-only verification"); + return { + verified: true, + method: "crypto-only", + warning: "Lightning verification skipped - unknown method" + }; + } + } else { + console.warn("\u{1F6A8} DEMO MODE: Lightning payment verification bypassed - FOR DEVELOPMENT ONLY"); + return { + verified: true, + method: "demo-mode", + warning: "DEMO MODE - Lightning verification bypassed" + }; + } + } catch (error) { + console.error("\u274C Payment verification failed:", error); + return { + verified: false, + reason: error.message, + stage: "error" + }; + } + } + // ============================================ + // SESSION MANAGEMENT + // ============================================ + // ============================================ + // REWORKED session activation methods + // ============================================ + async safeActivateSession(sessionType, preimage, paymentHash) { + try { + console.log(`\u{1F680} Attempting to activate ${sessionType} session...`); + if (!sessionType || !preimage || !paymentHash) { + return { + success: false, + reason: "Missing required parameters: sessionType, preimage, or paymentHash" + }; + } + try { + this.validateSessionType(sessionType); + } catch (error) { + return { success: false, reason: error.message }; + } + if (this.hasActiveSession()) { + return { + success: false, + reason: "Active session already exists. Please wait for it to expire or disconnect." + }; + } + if (sessionType === "demo") { + if (!this.isDemoPreimage(preimage)) { + return { + success: false, + reason: "Invalid demo preimage format. Please use the generated demo preimage." + }; + } + const userFingerprint = this.generateAdvancedUserFingerprint(); + const demoCheck = this.checkEnhancedDemoSessionLimits(userFingerprint); + if (!demoCheck.allowed) { + console.log(`\u26A0\uFE0F Demo session cooldown active, but allowing activation for development`); + if (demoCheck.reason === "global_limit_exceeded") { + return { + success: false, + reason: demoCheck.message, + demoLimited: true, + timeUntilNext: demoCheck.timeUntilNext, + remaining: demoCheck.remaining + }; + } + console.log(`\u{1F504} Bypassing demo cooldown for development purposes`); + } + if (this.activeDemoSessions.has(preimage)) { + if (!this.currentSession || !this.hasActiveSession()) { + console.log(`\u{1F504} Demo session with preimage ${preimage.substring(0, 16)}... was interrupted, allowing reactivation`); + this.activeDemoSessions.delete(preimage); + } else { + return { + success: false, + reason: "Demo session with this preimage is already active", + demoLimited: true + }; + } + } + } + let verificationResult; + if (sessionType === "demo") { + console.log("\u{1F3AE} Using special demo verification for activation..."); + verificationResult = await this.verifyDemoSessionForActivation(preimage, paymentHash); + } else { + verificationResult = await this.verifyPayment(preimage, paymentHash); + } + if (!verificationResult.verified) { + return { + success: false, + reason: verificationResult.reason, + stage: verificationResult.stage, + method: verificationResult.method, + demoLimited: verificationResult.demoLimited, + timeUntilNext: verificationResult.timeUntilNext, + remaining: verificationResult.remaining + }; + } + const session = this.activateSession(sessionType, preimage); + console.log(`\u2705 Session activated successfully: ${sessionType} via ${verificationResult.method}`); + return { + success: true, + sessionType, + method: verificationResult.method, + details: verificationResult, + timeLeft: this.getTimeLeft(), + sessionId: session.id, + warning: verificationResult.warning, + isDemo: verificationResult.isDemo || false, + remaining: verificationResult.remaining + }; + } catch (error) { + console.error("\u274C Session activation failed:", error); + return { + success: false, + reason: error.message, + method: "error" + }; + } + } + // REWORKED session activation + activateSession(sessionType, preimage) { + if (this.hasActiveSession()) { + return this.currentSession; + } + if (this.sessionTimer) { + clearInterval(this.sessionTimer); + this.sessionTimer = null; + } + const pricing = this.sessionPrices[sessionType]; + const now = Date.now(); + let duration; + if (sessionType === "demo") { + duration = this.demoSessionMaxDuration; + } else { + duration = pricing.hours * 60 * 60 * 1e3; + } + const expiresAt = now + duration; + const sessionId = Array.from(crypto.getRandomValues(new Uint8Array(16))).map((b) => b.toString(16).padStart(2, "0")).join(""); + this.currentSession = { + id: sessionId, + type: sessionType, + startTime: now, + expiresAt, + preimage, + isDemo: sessionType === "demo", + securityLevel: this.getSecurityLevelForSession(sessionType) + }; + this.startSessionTimer(); + if (sessionType === "demo") { + setTimeout(() => { + this.handleDemoSessionExpiry(preimage); + }, duration); + } + const durationMinutes = Math.round(duration / (60 * 1e3)); + const securityLevel = this.currentSession ? this.currentSession.securityLevel : "unknown"; + console.log(`\u{1F4C5} Session ${sessionId.substring(0, 8)}... activated for ${durationMinutes} minutes with ${securityLevel} security`); + if (sessionType === "demo") { + this.activeDemoSessions.add(preimage); + this.usedPreimages.add(preimage); + console.log(`\u{1F310} Demo session added to active sessions. Total: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`); + } + const activatedSession = this.currentSession; + setTimeout(() => { + if (activatedSession) { + this.notifySessionActivated(activatedSession); + } + if (window.webrtcManager && window.webrtcManager.configureSecurityForSession && activatedSession) { + const securityLevel2 = activatedSession.securityLevel || this.getSecurityLevelForSession(sessionType); + window.webrtcManager.configureSecurityForSession(sessionType, securityLevel2); + } + }, 100); + return this.currentSession; + } + // UPDATED method for getting session information + getSessionInfo() { + if (!this.currentSession) { + return null; + } + const securityLevel = this.getSecurityLevelForSession(this.currentSession.type); + const pricing = this.sessionPrices[this.currentSession.type]; + return { + ...this.currentSession, + securityLevel, + securityDescription: this.getSecurityDescription(securityLevel), + pricing, + timeLeft: this.getTimeLeft(), + isConnected: this.hasActiveSession() + }; + } + getSecurityDescription(level) { + const descriptions = { + "basic": { + title: "Basic Security", + features: [ + "End-to-end encryption", + "Basic key exchange", + "Rate limiting", + "Message integrity" + ], + limitations: [ + "No advanced obfuscation", + "No traffic padding", + "No decoy channels" + ] + }, + "enhanced": { + title: "Enhanced Security", + features: [ + "All basic features", + "ECDSA signatures", + "Metadata protection", + "Perfect forward secrecy", + "Nested encryption", + "Packet padding" + ], + limitations: [ + "Limited traffic obfuscation", + "No fake traffic generation" + ] + }, + "maximum": { + title: "Maximum Security", + features: [ + "All enhanced features", + "Traffic obfuscation", + "Fake traffic generation", + "Decoy channels", + "Anti-fingerprinting", + "Message chunking", + "Packet reordering protection" + ], + limitations: [] + } + }; + return descriptions[level] || descriptions["basic"]; + } + notifySessionActivated(session = null) { + const targetSession = session || this.currentSession; + if (!targetSession) return; + if (targetSession.notified) { + return; + } + const timeLeft = Math.max(0, targetSession.expiresAt - Date.now()); + const sessionType = targetSession.type; + if (window.updateSessionTimer) { + window.updateSessionTimer(timeLeft, sessionType); + } + document.dispatchEvent(new CustomEvent("session-activated", { + detail: { + sessionId: targetSession.id, + timeLeft, + sessionType, + isDemo: targetSession.isDemo, + timestamp: Date.now() + } + })); + if (window.forceUpdateHeader) { + window.forceUpdateHeader(timeLeft, sessionType); + } + if (window.debugSessionManager) { + window.debugSessionManager(); + } + targetSession.notified = true; + } + handleDemoSessionExpiry(preimage) { + if (this.currentSession && this.currentSession.preimage === preimage) { + const userFingerprint = this.generateAdvancedUserFingerprint(); + const sessionDuration = Date.now() - this.currentSession.startTime; + this.registerDemoSessionCompletion(userFingerprint, sessionDuration, preimage); + console.log(`\u23F0 Demo session auto-expired for preimage ${preimage.substring(0, 16)}...`); + } + } + startSessionTimer() { + if (this.sessionTimer) { + clearInterval(this.sessionTimer); + } + this.sessionTimer = setInterval(() => { + if (!this.hasActiveSession()) { + this.expireSession(); + } + }, 6e4); + } + expireSession() { + if (this.sessionTimer) { + clearInterval(this.sessionTimer); + this.sessionTimer = null; + } + const expiredSession = this.currentSession; + if (expiredSession && expiredSession.isDemo) { + const userFingerprint = this.generateAdvancedUserFingerprint(); + const sessionDuration = Date.now() - expiredSession.startTime; + this.registerDemoSessionCompletion(userFingerprint, sessionDuration, expiredSession.preimage); + } + this.currentSession = null; + if (expiredSession) { + console.log(`\u23F0 Session ${expiredSession.id.substring(0, 8)}... expired`); + } + if (this.onSessionExpired) { + this.onSessionExpired(); + } + } + hasActiveSession() { + if (!this.currentSession) { + return false; + } + const isActive = Date.now() < this.currentSession.expiresAt; + return isActive; + } + getTimeLeft() { + if (!this.currentSession) return 0; + return Math.max(0, this.currentSession.expiresAt - Date.now()); + } + forceUpdateTimer() { + if (this.currentSession) { + const timeLeft = this.getTimeLeft(); + if (window.DEBUG_MODE && Math.floor(Date.now() / 3e4) !== Math.floor((Date.now() - 1e3) / 3e4)) { + console.log(`\u23F1\uFE0F Timer updated: ${Math.ceil(timeLeft / 1e3)}s left`); + } + return timeLeft; + } + return 0; + } + // ============================================ + // DEMO MODE: Custom Methods + // ============================================ + // UPDATED demo session creation + createDemoSession() { + const userFingerprint = this.generateAdvancedUserFingerprint(); + const demoCheck = this.checkEnhancedDemoSessionLimits(userFingerprint); + if (!demoCheck.allowed) { + return { + success: false, + reason: demoCheck.message, + timeUntilNext: demoCheck.timeUntilNext, + remaining: demoCheck.remaining, + blockingReason: demoCheck.reason + }; + } + if (this.activeDemoSessions.size >= this.maxGlobalDemoSessions) { + return { + success: false, + reason: `Too many demo sessions active globally (${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}). Please try again later.`, + blockingReason: "global_limit", + globalActive: this.activeDemoSessions.size, + globalLimit: this.maxGlobalDemoSessions + }; + } + try { + const demoPreimage = this.generateSecureDemoPreimage(); + const demoPaymentHash = "demo_" + Array.from(crypto.getRandomValues(new Uint8Array(16))).map((b) => b.toString(16).padStart(2, "0")).join(""); + return { + success: true, + sessionType: "demo", + preimage: demoPreimage, + paymentHash: demoPaymentHash, + duration: this.sessionPrices.demo.hours, + durationMinutes: Math.round(this.demoSessionMaxDuration / (60 * 1e3)), + warning: `Demo session - limited to ${Math.round(this.demoSessionMaxDuration / (60 * 1e3))} minutes`, + remaining: demoCheck.remaining - 1, + globalActive: this.activeDemoSessions.size + 1, + globalLimit: this.maxGlobalDemoSessions + }; + } catch (error) { + console.error("Failed to create demo session:", error); + return { + success: false, + reason: "Failed to generate demo session. Please try again.", + remaining: demoCheck.remaining + }; + } + } + // UPDATED information about demo limits + getDemoSessionInfo() { + const userFingerprint = this.generateAdvancedUserFingerprint(); + const userData = this.demoSessions.get(userFingerprint); + const now = Date.now(); + if (!userData) { + return { + available: this.maxDemoSessionsPerUser, + used: 0, + total: this.maxDemoSessionsPerUser, + nextAvailable: "immediately", + cooldownMinutes: 0, + durationMinutes: Math.round(this.demoSessionMaxDuration / (60 * 1e3)), + canUseNow: this.activeDemoSessions.size < this.maxGlobalDemoSessions, + globalActive: this.activeDemoSessions.size, + globalLimit: this.maxGlobalDemoSessions, + debugInfo: "New user, no restrictions" + }; + } + const sessionsLast24h = userData.sessions.filter( + (session) => now - session.timestamp < this.demoCooldownPeriod + ); + const available = Math.max(0, this.maxDemoSessionsPerUser - sessionsLast24h.length); + let cooldownMs = 0; + let nextAvailable = "immediately"; + let blockingReason = null; + let debugInfo = ""; + if (this.activeDemoSessions.size >= this.maxGlobalDemoSessions) { + nextAvailable = "when global limit decreases"; + blockingReason = "global_limit"; + debugInfo = `Global limit: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`; + } else if (available === 0) { + const oldestSession = Math.min(...sessionsLast24h.map((s) => s.timestamp)); + cooldownMs = this.demoCooldownPeriod - (now - oldestSession); + nextAvailable = `${Math.ceil(cooldownMs / (60 * 1e3))} minutes`; + blockingReason = "daily_limit"; + debugInfo = `Daily limit reached: ${sessionsLast24h.length}/${this.maxDemoSessionsPerUser}`; + } else if (userData.lastUsed && now - userData.lastUsed < this.demoSessionCooldown) { + cooldownMs = this.demoSessionCooldown - (now - userData.lastUsed); + nextAvailable = `${Math.ceil(cooldownMs / (60 * 1e3))} minutes`; + blockingReason = "session_cooldown"; + const lastUsedMinutes = Math.round((now - userData.lastUsed) / (60 * 1e3)); + debugInfo = `Cooldown active: last used ${lastUsedMinutes}min ago, need ${Math.ceil(cooldownMs / (60 * 1e3))}min more`; + } else { + const completedSessions = this.completedDemoSessions.get(userFingerprint) || []; + const recentCompletedSessions = completedSessions.filter( + (session) => now - session.endTime < this.minTimeBetweenCompletedSessions + ); + if (recentCompletedSessions.length > 0) { + const lastCompletedSession = Math.max(...recentCompletedSessions.map((s) => s.endTime)); + cooldownMs = this.minTimeBetweenCompletedSessions - (now - lastCompletedSession); + nextAvailable = `${Math.ceil(cooldownMs / (60 * 1e3))} minutes`; + blockingReason = "completion_cooldown"; + const completedMinutes = Math.round((now - lastCompletedSession) / (60 * 1e3)); + debugInfo = `Completion cooldown: last session ended ${completedMinutes}min ago`; + } else { + debugInfo = `Ready to use: ${available} sessions available`; + } + } + const canUseNow = available > 0 && cooldownMs <= 0 && this.activeDemoSessions.size < this.maxGlobalDemoSessions; + return { + available, + used: sessionsLast24h.length, + total: this.maxDemoSessionsPerUser, + nextAvailable, + cooldownMinutes: Math.ceil(cooldownMs / (60 * 1e3)), + durationMinutes: Math.round(this.demoSessionMaxDuration / (60 * 1e3)), + canUseNow, + blockingReason, + globalActive: this.activeDemoSessions.size, + globalLimit: this.maxGlobalDemoSessions, + completionCooldownMinutes: Math.round(this.minTimeBetweenCompletedSessions / (60 * 1e3)), + sessionCooldownMinutes: Math.round(this.demoSessionCooldown / (60 * 1e3)), + debugInfo, + lastUsed: userData.lastUsed ? new Date(userData.lastUsed).toLocaleString() : "Never" + }; + } + // ============================================ + // ADDITIONAL VERIFICATION METHODS + // ============================================ + // Verification method via LND (Lightning Network Daemon) + async verifyPaymentLND(preimage, paymentHash) { + try { + if (!this.verificationConfig.nodeUrl || !this.verificationConfig.macaroon) { + throw new Error("LND configuration missing"); + } + const response = await fetch(`${this.verificationConfig.nodeUrl}/v1/invoice/${paymentHash}`, { + method: "GET", + headers: { + "Grpc-Metadata-macaroon": this.verificationConfig.macaroon, + "Content-Type": "application/json" + }, + signal: AbortSignal.timeout(1e4) + }); + if (!response.ok) { + throw new Error(`LND API request failed: ${response.status}`); + } + const invoiceData = await response.json(); + if (invoiceData.settled && invoiceData.r_preimage === preimage) { + return { + verified: true, + amount: invoiceData.value, + method: "lnd", + timestamp: Date.now() + }; + } + return { verified: false, reason: "LND verification failed", method: "lnd" }; + } catch (error) { + console.error("LND payment verification failed:", error); + return { verified: false, reason: error.message, method: "lnd" }; + } + } + // Verification method via CLN (Core Lightning) + async verifyPaymentCLN(preimage, paymentHash) { + try { + if (!this.verificationConfig.nodeUrl) { + throw new Error("CLN configuration missing"); + } + const response = await fetch(`${this.verificationConfig.nodeUrl}/v1/listinvoices`, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + payment_hash: paymentHash + }), + signal: AbortSignal.timeout(1e4) + }); + if (!response.ok) { + throw new Error(`CLN API request failed: ${response.status}`); + } + const data = await response.json(); + if (data.invoices && data.invoices.length > 0) { + const invoice = data.invoices[0]; + if (invoice.status === "paid" && invoice.payment_preimage === preimage) { + return { + verified: true, + amount: invoice.amount_msat / 1e3, + method: "cln", + timestamp: Date.now() + }; + } + } + return { verified: false, reason: "CLN verification failed", method: "cln" }; + } catch (error) { + console.error("CLN payment verification failed:", error); + return { verified: false, reason: error.message, method: "cln" }; + } + } + // Verification method via BTCPay Server + async verifyPaymentBTCPay(preimage, paymentHash) { + try { + if (!this.verificationConfig.apiUrl || !this.verificationConfig.apiKey) { + throw new Error("BTCPay Server configuration missing"); + } + const response = await fetch(`${this.verificationConfig.apiUrl}/api/v1/invoices/${paymentHash}`, { + method: "GET", + headers: { + "Authorization": `Bearer ${this.verificationConfig.apiKey}`, + "Content-Type": "application/json" + }, + signal: AbortSignal.timeout(1e4) + }); + if (!response.ok) { + throw new Error(`BTCPay API request failed: ${response.status}`); + } + const invoiceData = await response.json(); + if (invoiceData.status === "Settled" && invoiceData.payment && invoiceData.payment.preimage === preimage) { + return { + verified: true, + amount: invoiceData.amount, + method: "btcpay", + timestamp: Date.now() + }; + } + return { verified: false, reason: "BTCPay verification failed", method: "btcpay" }; + } catch (error) { + console.error("BTCPay payment verification failed:", error); + return { verified: false, reason: error.message, method: "btcpay" }; + } + } + // ============================================ + // UTILITY METHODS + // ============================================ + // Creating a regular invoice (not a demo) + createInvoice(sessionType) { + this.validateSessionType(sessionType); + const pricing = this.sessionPrices[sessionType]; + const randomBytes = crypto.getRandomValues(new Uint8Array(32)); + const timestamp = Date.now(); + const sessionEntropy = crypto.getRandomValues(new Uint8Array(16)); + const combinedEntropy = new Uint8Array(48); + combinedEntropy.set(randomBytes, 0); + combinedEntropy.set(new Uint8Array(new BigUint64Array([BigInt(timestamp)]).buffer), 32); + combinedEntropy.set(sessionEntropy, 40); + const paymentHash = Array.from(crypto.getRandomValues(new Uint8Array(32))).map((b) => b.toString(16).padStart(2, "0")).join(""); + return { + amount: pricing.sats, + memo: `SecureBit.chat ${sessionType} session (${pricing.hours}h) - ${timestamp}`, + sessionType, + timestamp, + paymentHash, + lightningAddress: this.staticLightningAddress, + entropy: Array.from(sessionEntropy).map((b) => b.toString(16).padStart(2, "0")).join(""), + expiresAt: timestamp + this.verificationConfig.invoiceExpiryMinutes * 60 * 1e3 + }; + } + // Checking if a session can be activated + canActivateSession() { + return !this.hasActiveSession(); + } + // Reset session (if there are security errors) + resetSession() { + if (this.sessionTimer) { + clearInterval(this.sessionTimer); + this.sessionTimer = null; + } + const resetSession = this.currentSession; + if (resetSession && resetSession.isDemo) { + const userFingerprint = this.generateAdvancedUserFingerprint(); + const sessionDuration = Date.now() - resetSession.startTime; + this.registerDemoSessionCompletion(userFingerprint, sessionDuration, resetSession.preimage); + } + this.currentSession = null; + this.sessionStartTime = null; + this.sessionEndTime = null; + if (resetSession && resetSession.preimage) { + this.activeDemoSessions.delete(resetSession.preimage); + } + document.dispatchEvent(new CustomEvent("session-reset", { + detail: { + timestamp: Date.now(), + reason: "security_reset" + } + })); + setTimeout(() => { + if (this.currentSession) { + this.currentSession = null; + } + }, 100); + } + // Cleaning old preimages (every 24 hours) + startPreimageCleanup() { + this.preimageCleanupInterval = setInterval(() => { + if (this.usedPreimages.size > 1e4) { + const oldSize = this.usedPreimages.size; + this.usedPreimages.clear(); + console.log(`\u{1F9F9} Cleaned ${oldSize} old preimages for memory management`); + } + }, 24 * 60 * 60 * 1e3); + } + // Complete manager cleanup + cleanup() { + if (this.sessionTimer) { + clearInterval(this.sessionTimer); + this.sessionTimer = null; + } + if (this.preimageCleanupInterval) { + clearInterval(this.preimageCleanupInterval); + this.preimageCleanupInterval = null; + } + if (this.currentSession && this.currentSession.isDemo) { + const userFingerprint = this.generateAdvancedUserFingerprint(); + const sessionDuration = Date.now() - this.currentSession.startTime; + this.registerDemoSessionCompletion(userFingerprint, sessionDuration, this.currentSession.preimage); + } + this.currentSession = null; + this.sessionStartTime = null; + this.sessionEndTime = null; + if (this.currentSession && this.currentSession.preimage) { + this.activeDemoSessions.delete(this.currentSession.preimage); + } + document.dispatchEvent(new CustomEvent("session-cleanup", { + detail: { + timestamp: Date.now(), + reason: "complete_cleanup" + } + })); + setTimeout(() => { + if (this.currentSession) { + this.currentSession = null; + } + }, 100); + } + getUsageStats() { + const stats = { + totalDemoUsers: this.demoSessions.size, + usedPreimages: this.usedPreimages.size, + activeDemoSessions: this.activeDemoSessions.size, + globalDemoLimit: this.maxGlobalDemoSessions, + currentSession: this.currentSession ? { + type: this.currentSession.type, + timeLeft: this.getTimeLeft(), + isDemo: this.currentSession.isDemo + } : null, + config: { + maxDemoSessions: this.maxDemoSessionsPerUser, + demoCooldown: this.demoSessionCooldown / (60 * 1e3), + demoMaxDuration: this.demoSessionMaxDuration / (60 * 1e3), + completionCooldown: this.minTimeBetweenCompletedSessions / (60 * 1e3) + } + }; + return stats; + } + getVerifiedDemoSession() { + const userFingerprint = this.generateAdvancedUserFingerprint(); + const userData = this.demoSessions.get(userFingerprint); + console.log("\u{1F50D} Searching for verified demo session:", { + userFingerprint: userFingerprint.substring(0, 12), + hasUserData: !!userData, + sessionsCount: userData?.sessions?.length || 0, + currentSession: this.currentSession ? { + type: this.currentSession.type, + timeLeft: this.getTimeLeft(), + isActive: this.hasActiveSession() + } : null + }); + if (!userData || !userData.sessions || userData.sessions.length === 0) { + console.log("\u274C No user data or sessions found"); + return null; + } + const lastSession = userData.sessions[userData.sessions.length - 1]; + if (!lastSession || !lastSession.preimage) { + console.log("\u274C Last session is invalid:", lastSession); + return null; + } + if (!this.isDemoPreimage(lastSession.preimage)) { + console.log("\u274C Last session preimage is not demo format:", lastSession.preimage.substring(0, 16) + "..."); + return null; + } + if (this.activeDemoSessions.has(lastSession.preimage)) { + console.log("\u26A0\uFE0F Demo session is already in activeDemoSessions, checking if truly active..."); + if (this.hasActiveSession()) { + console.log("\u274C Demo session is truly active, cannot reactivate"); + return null; + } else { + console.log("\u{1F504} Demo session was interrupted, can be reactivated"); + } + } + const verifiedSession = { + preimage: lastSession.preimage, + paymentHash: lastSession.paymentHash || "demo_" + Date.now(), + sessionType: "demo", + timestamp: lastSession.timestamp + }; + console.log("\u2705 Found verified demo session:", { + preimage: verifiedSession.preimage.substring(0, 16) + "...", + timestamp: new Date(verifiedSession.timestamp).toLocaleTimeString(), + canActivate: !this.hasActiveSession() + }); + return verifiedSession; + } + checkDemoSessionLimits(userFingerprint) { + const userData = this.demoSessions.get(userFingerprint); + const now = Date.now(); + console.log(`\u{1F50D} Checking demo limits for user ${userFingerprint.substring(0, 12)}...`); + if (this.activeDemoSessions.size >= this.maxGlobalDemoSessions) { + console.log(`\u274C Global demo limit reached: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`); + return { + allowed: false, + reason: "global_limit_exceeded", + message: `Too many demo sessions active globally (${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}). Please try again later.`, + remaining: 0, + debugInfo: `Global sessions: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}` + }; + } + if (!userData) { + console.log(`\u2705 First demo session for user ${userFingerprint.substring(0, 12)}`); + return { + allowed: true, + reason: "first_demo_session", + remaining: this.maxDemoSessionsPerUser, + debugInfo: "First time user" + }; + } + const sessionsLast24h = userData.sessions.filter( + (session) => now - session.timestamp < this.demoCooldownPeriod + ); + console.log(`\u{1F4CA} Sessions in last 24h for user ${userFingerprint.substring(0, 12)}: ${sessionsLast24h.length}/${this.maxDemoSessionsPerUser}`); + if (sessionsLast24h.length >= this.maxDemoSessionsPerUser) { + const oldestSession = Math.min(...sessionsLast24h.map((s) => s.timestamp)); + const timeUntilNext = this.demoCooldownPeriod - (now - oldestSession); + console.log(`\u274C Daily demo limit exceeded for user ${userFingerprint.substring(0, 12)}`); + return { + allowed: false, + reason: "daily_limit_exceeded", + timeUntilNext, + message: `Daily demo limit reached (${this.maxDemoSessionsPerUser}/day). Next session available in ${Math.ceil(timeUntilNext / (60 * 1e3))} minutes.`, + remaining: 0, + debugInfo: `Used ${sessionsLast24h.length}/${this.maxDemoSessionsPerUser} today` + }; + } + if (userData.lastUsed && now - userData.lastUsed < this.demoSessionCooldown) { + const timeUntilNext = this.demoSessionCooldown - (now - userData.lastUsed); + const minutesLeft = Math.ceil(timeUntilNext / (60 * 1e3)); + console.log(`\u23F0 Cooldown active for user ${userFingerprint.substring(0, 12)}: ${minutesLeft} minutes`); + return { + allowed: false, + reason: "session_cooldown", + timeUntilNext, + message: `Please wait ${minutesLeft} minutes between demo sessions. This prevents abuse and ensures fair access for all users.`, + remaining: this.maxDemoSessionsPerUser - sessionsLast24h.length, + debugInfo: `Cooldown: ${minutesLeft}min left, last used: ${Math.round((now - userData.lastUsed) / (60 * 1e3))}min ago` + }; + } + const completedSessions = this.completedDemoSessions.get(userFingerprint) || []; + const recentCompletedSessions = completedSessions.filter( + (session) => now - session.endTime < this.minTimeBetweenCompletedSessions + ); + if (recentCompletedSessions.length > 0) { + const lastCompletedSession = Math.max(...recentCompletedSessions.map((s) => s.endTime)); + const timeUntilNext = this.minTimeBetweenCompletedSessions - (now - lastCompletedSession); + console.log(`\u23F0 Recent session completed, waiting period active for user ${userFingerprint.substring(0, 12)}`); + return { + allowed: false, + reason: "recent_session_completed", + timeUntilNext, + message: `Please wait ${Math.ceil(timeUntilNext / (60 * 1e3))} minutes after your last session before starting a new one.`, + remaining: this.maxDemoSessionsPerUser - sessionsLast24h.length, + debugInfo: `Last session ended ${Math.round((now - lastCompletedSession) / (60 * 1e3))}min ago` + }; + } + console.log(`\u2705 Demo session approved for user ${userFingerprint.substring(0, 12)}`); + return { + allowed: true, + reason: "within_limits", + remaining: this.maxDemoSessionsPerUser - sessionsLast24h.length, + debugInfo: `Available: ${this.maxDemoSessionsPerUser - sessionsLast24h.length}/${this.maxDemoSessionsPerUser}` + }; + } + createDemoSessionForActivation() { + const userFingerprint = this.generateAdvancedUserFingerprint(); + if (this.activeDemoSessions.size >= this.maxGlobalDemoSessions) { + return { + success: false, + reason: `Too many demo sessions active globally (${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}). Please try again later.`, + blockingReason: "global_limit" + }; + } + try { + const demoPreimage = this.generateSecureDemoPreimage(); + const demoPaymentHash = "demo_" + Array.from(crypto.getRandomValues(new Uint8Array(16))).map((b) => b.toString(16).padStart(2, "0")).join(""); + console.log("\u{1F504} Created demo session for activation:", { + preimage: demoPreimage.substring(0, 16) + "...", + paymentHash: demoPaymentHash.substring(0, 16) + "..." + }); + return { + success: true, + sessionType: "demo", + preimage: demoPreimage, + paymentHash: demoPaymentHash, + duration: this.sessionPrices.demo.hours, + durationMinutes: Math.round(this.demoSessionMaxDuration / (60 * 1e3)), + warning: `Demo session - limited to ${Math.round(this.demoSessionMaxDuration / (60 * 1e3))} minutes`, + globalActive: this.activeDemoSessions.size + 1, + globalLimit: this.maxGlobalDemoSessions + }; + } catch (error) { + console.error("Failed to create demo session for activation:", error); + return { + success: false, + reason: "Failed to generate demo session for activation. Please try again." + }; + } + } + async verifyDemoSessionForActivation(preimage, paymentHash) { + console.log("\u{1F3AE} Verifying demo session for activation (bypassing limits)..."); + try { + if (!preimage || !paymentHash) { + throw new Error("Missing preimage or payment hash"); + } + if (typeof preimage !== "string" || typeof paymentHash !== "string") { + throw new Error("Preimage and payment hash must be strings"); + } + if (!this.isDemoPreimage(preimage)) { + throw new Error("Invalid demo preimage format"); + } + const entropy = this.calculateEntropy(preimage); + if (entropy < 3.5) { + throw new Error(`Demo preimage has insufficient entropy: ${entropy.toFixed(2)}`); + } + if (this.activeDemoSessions.has(preimage)) { + throw new Error("Demo session with this preimage is already active"); + } + console.log("\u2705 Demo session verified for activation successfully"); + return { + verified: true, + method: "demo-activation", + sessionType: "demo", + isDemo: true, + warning: "Demo session - limited duration (6 minutes)" + }; + } catch (error) { + console.error("\u274C Demo session verification for activation failed:", error); + return { + verified: false, + reason: error.message, + stage: "demo-activation" + }; + } + } +}; + +// src/components/ui/SessionTimer.jsx +var SessionTimer = ({ timeLeft, sessionType, sessionManager, onDisconnect }) => { + const [currentTime, setCurrentTime] = React.useState(timeLeft || 0); + const [showExpiredMessage, setShowExpiredMessage] = React.useState(false); + const [initialized, setInitialized] = React.useState(false); + const [connectionBroken, setConnectionBroken] = React.useState(false); + const [loggedHidden, setLoggedHidden] = React.useState(false); + React.useEffect(() => { + if (connectionBroken) { + if (!loggedHidden) { + console.log("\u23F1\uFE0F SessionTimer initialization skipped - connection broken"); + setLoggedHidden(true); + } + return; + } + let initialTime = 0; + if (sessionManager?.hasActiveSession()) { + initialTime = sessionManager.getTimeLeft(); + } else if (timeLeft && timeLeft > 0) { + initialTime = timeLeft; + } + if (initialTime <= 0) { + setCurrentTime(0); + setInitialized(false); + setLoggedHidden(true); + return; + } + if (connectionBroken) { + setCurrentTime(0); + setInitialized(false); + setLoggedHidden(true); + return; + } + setCurrentTime(initialTime); + setInitialized(true); + setLoggedHidden(false); + }, [sessionManager, connectionBroken]); + React.useEffect(() => { + if (connectionBroken) { + if (!loggedHidden) { + setLoggedHidden(true); + } + return; + } + if (timeLeft && timeLeft > 0) { + setCurrentTime(timeLeft); + } + setLoggedHidden(false); + }, [timeLeft, connectionBroken]); + React.useEffect(() => { + if (!initialized) { + return; + } + if (connectionBroken) { + if (!loggedHidden) { + setLoggedHidden(true); + } + return; + } + if (!currentTime || currentTime <= 0 || !sessionManager) { + return; + } + const interval = setInterval(() => { + if (connectionBroken) { + setCurrentTime(0); + clearInterval(interval); + return; + } + if (sessionManager?.hasActiveSession()) { + const newTime = sessionManager.getTimeLeft(); + setCurrentTime(newTime); + if (window.DEBUG_MODE && Math.floor(Date.now() / 3e4) !== Math.floor((Date.now() - 1e3) / 3e4)) { + console.log("\u23F1\uFE0F Timer tick:", Math.floor(newTime / 1e3) + "s"); + } + if (newTime <= 0) { + setShowExpiredMessage(true); + setTimeout(() => setShowExpiredMessage(false), 5e3); + clearInterval(interval); + } + } else { + setCurrentTime(0); + clearInterval(interval); + } + }, 1e3); + return () => { + clearInterval(interval); + }; + }, [initialized, currentTime, sessionManager, connectionBroken]); + React.useEffect(() => { + const handleSessionTimerUpdate = (event) => { + if (connectionBroken) { + return; + } + if (event.detail.timeLeft && event.detail.timeLeft > 0) { + setCurrentTime(event.detail.timeLeft); + } + }; + const handleForceHeaderUpdate = (event) => { + if (connectionBroken) { + return; + } + if (sessionManager && sessionManager.hasActiveSession()) { + const newTime = sessionManager.getTimeLeft(); + setCurrentTime(newTime); + } else { + setCurrentTime(event.detail.timeLeft); + } + }; + const handlePeerDisconnect = (event) => { + setConnectionBroken(true); + setCurrentTime(0); + setShowExpiredMessage(false); + setLoggedHidden(false); + }; + const handleNewConnection = (event) => { + setConnectionBroken(false); + setLoggedHidden(false); + }; + const handleConnectionCleaned = (event) => { + setConnectionBroken(true); + setCurrentTime(0); + setShowExpiredMessage(false); + setInitialized(false); + setLoggedHidden(false); + }; + const handleSessionReset = (event) => { + setConnectionBroken(true); + setCurrentTime(0); + setShowExpiredMessage(false); + setInitialized(false); + setLoggedHidden(false); + }; + const handleSessionCleanup = (event) => { + setConnectionBroken(true); + setCurrentTime(0); + setShowExpiredMessage(false); + setInitialized(false); + setLoggedHidden(false); + }; + const handleDisconnected = (event) => { + setConnectionBroken(true); + setCurrentTime(0); + setShowExpiredMessage(false); + setInitialized(false); + setLoggedHidden(false); + }; + document.addEventListener("session-timer-update", handleSessionTimerUpdate); + document.addEventListener("force-header-update", handleForceHeaderUpdate); + document.addEventListener("peer-disconnect", handlePeerDisconnect); + document.addEventListener("new-connection", handleNewConnection); + document.addEventListener("connection-cleaned", handleConnectionCleaned); + document.addEventListener("session-reset", handleSessionReset); + document.addEventListener("session-cleanup", handleSessionCleanup); + document.addEventListener("disconnected", handleDisconnected); + return () => { + document.removeEventListener("session-timer-update", handleSessionTimerUpdate); + document.removeEventListener("force-header-update", handleForceHeaderUpdate); + document.removeEventListener("peer-disconnect", handlePeerDisconnect); + document.removeEventListener("new-connection", handleNewConnection); + document.removeEventListener("connection-cleaned", handleConnectionCleaned); + document.removeEventListener("session-reset", handleSessionReset); + document.removeEventListener("session-cleanup", handleSessionCleanup); + document.removeEventListener("disconnected", handleDisconnected); + }; + }, [sessionManager]); + if (showExpiredMessage) { + return React.createElement("div", { + className: "session-timer expired flex items-center space-x-2 px-3 py-1.5 rounded-lg animate-pulse", + style: { background: "linear-gradient(135deg, rgba(239, 68, 68, 0.2) 0%, rgba(220, 38, 38, 0.2) 100%)" } + }, [ + React.createElement("i", { + key: "icon", + className: "fas fa-exclamation-triangle text-red-400" + }), + React.createElement("span", { + key: "message", + className: "text-red-400 text-sm font-medium" + }, "Session Expired!") + ]); + } + if (!sessionManager) { + if (!loggedHidden) { + console.log("\u23F1\uFE0F SessionTimer hidden - no sessionManager"); + setLoggedHidden(true); + } + return null; + } + if (connectionBroken) { + if (!loggedHidden) { + console.log("\u23F1\uFE0F SessionTimer hidden - connection broken"); + setLoggedHidden(true); + } + return null; + } + if (!currentTime || currentTime <= 0) { + if (!loggedHidden) { + console.log("\u23F1\uFE0F SessionTimer hidden - no time left, currentTime:", currentTime); + setLoggedHidden(true); + } + return null; + } + if (loggedHidden) { + setLoggedHidden(false); + } + const totalMinutes = Math.floor(currentTime / (60 * 1e3)); + const totalSeconds = Math.floor(currentTime / 1e3); + const isDemo = sessionType === "demo"; + const isWarning = isDemo ? totalMinutes <= 2 : totalMinutes <= 10; + const isCritical = isDemo ? totalSeconds <= 60 : totalMinutes <= 5; + const formatTime = (ms) => { + const hours = Math.floor(ms / (60 * 60 * 1e3)); + const minutes = Math.floor(ms % (60 * 60 * 1e3) / (60 * 1e3)); + const seconds = Math.floor(ms % (60 * 1e3) / 1e3); + if (hours > 0) { + return `${hours}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`; + } else { + return `${minutes}:${seconds.toString().padStart(2, "0")}`; + } + }; + const getTimerStyle = () => { + const totalDuration = sessionType === "demo" ? 6 * 60 * 1e3 : 60 * 60 * 1e3; + const timeProgress = (totalDuration - currentTime) / totalDuration; + let backgroundColor, textColor, iconColor, iconClass, shouldPulse; + if (timeProgress <= 0.33) { + backgroundColor = "linear-gradient(135deg, rgba(34, 197, 94, 0.15) 0%, rgba(22, 163, 74, 0.15) 100%)"; + textColor = "text-green-400"; + iconColor = "text-green-400"; + iconClass = "fas fa-clock"; + shouldPulse = false; + } else if (timeProgress <= 0.66) { + backgroundColor = "linear-gradient(135deg, rgba(234, 179, 8, 0.15) 0%, rgba(202, 138, 4, 0.15) 100%)"; + textColor = "text-yellow-400"; + iconColor = "text-yellow-400"; + iconClass = "fas fa-clock"; + shouldPulse = false; + } else { + backgroundColor = "linear-gradient(135deg, rgba(239, 68, 68, 0.15) 0%, rgba(220, 38, 38, 0.15) 100%)"; + textColor = "text-red-400"; + iconColor = "text-red-400"; + iconClass = "fas fa-exclamation-triangle"; + shouldPulse = true; + } + return { backgroundColor, textColor, iconColor, iconClass, shouldPulse }; + }; + const timerStyle = getTimerStyle(); + const handleTimerClick = () => { + if (onDisconnect && typeof onDisconnect === "function") { + onDisconnect(); + } + }; + return React.createElement("div", { + className: `session-timer flex items-center space-x-2 px-3 py-1.5 rounded-lg transition-all duration-500 cursor-pointer hover:opacity-80 ${isDemo ? "demo-session" : ""} ${timerStyle.shouldPulse ? "animate-pulse" : ""}`, + style: { background: timerStyle.backgroundColor }, + onClick: handleTimerClick, + title: "Click to disconnect and clear session" + }, [ + React.createElement("i", { + key: "icon", + className: `${timerStyle.iconClass} ${timerStyle.iconColor}` + }), + React.createElement("span", { + key: "time", + className: `text-sm font-mono font-semibold ${timerStyle.textColor}` + }, formatTime(currentTime)), + React.createElement("div", { + key: "progress", + className: "ml-2 w-16 h-1 bg-gray-700 rounded-full overflow-hidden" + }, [ + React.createElement("div", { + key: "progress-bar", + className: `${timerStyle.textColor.replace("text-", "bg-")} h-full rounded-full transition-all duration-500`, + style: { + width: `${Math.max(0, Math.min(100, currentTime / (sessionType === "demo" ? 6 * 60 * 1e3 : 60 * 60 * 1e3) * 100))}%` + } + }) + ]) + ]); +}; +window.SessionTimer = SessionTimer; +window.updateSessionTimer = (newTimeLeft, newSessionType) => { + document.dispatchEvent(new CustomEvent("session-timer-update", { + detail: { timeLeft: newTimeLeft, sessionType: newSessionType } + })); +}; + +// src/components/ui/Header.jsx +var EnhancedMinimalHeader = ({ + status, + fingerprint, + verificationCode, + onDisconnect, + isConnected, + securityLevel, + sessionManager, + sessionTimeLeft, + webrtcManager +}) => { + const [currentTimeLeft, setCurrentTimeLeft] = React.useState(sessionTimeLeft || 0); + const [hasActiveSession, setHasActiveSession] = React.useState(false); + const [sessionType, setSessionType] = React.useState("unknown"); + const [realSecurityLevel, setRealSecurityLevel] = React.useState(null); + const [lastSecurityUpdate, setLastSecurityUpdate] = React.useState(0); + React.useEffect(() => { + let isUpdating = false; + let lastUpdateAttempt = 0; + const updateRealSecurityStatus = async () => { + const now = Date.now(); + if (now - lastUpdateAttempt < 1e4) { + return; + } + if (isUpdating) { + return; + } + isUpdating = true; + lastUpdateAttempt = now; + try { + if (!webrtcManager || !isConnected) { + return; + } + const activeWebrtcManager = webrtcManager; + let realSecurityData = null; + if (typeof activeWebrtcManager.getRealSecurityLevel === "function") { + realSecurityData = await activeWebrtcManager.getRealSecurityLevel(); + } else if (typeof activeWebrtcManager.calculateAndReportSecurityLevel === "function") { + realSecurityData = await activeWebrtcManager.calculateAndReportSecurityLevel(); + } else { + realSecurityData = await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(activeWebrtcManager); + } + if (window.DEBUG_MODE) { + console.log("\u{1F510} REAL security level calculated:", { + level: realSecurityData?.level, + score: realSecurityData?.score, + passedChecks: realSecurityData?.passedChecks, + totalChecks: realSecurityData?.totalChecks, + isRealData: realSecurityData?.isRealData, + sessionType: realSecurityData?.sessionType, + maxPossibleScore: realSecurityData?.maxPossibleScore, + verificationResults: realSecurityData?.verificationResults ? Object.keys(realSecurityData.verificationResults) : [] + }); + } + if (realSecurityData && realSecurityData.isRealData !== false) { + const currentScore = realSecurityLevel?.score || 0; + const newScore = realSecurityData.score || 0; + if (currentScore !== newScore || !realSecurityLevel) { + setRealSecurityLevel(realSecurityData); + setLastSecurityUpdate(now); + if (window.DEBUG_MODE) { + console.log("\u2705 Security level updated in header component:", { + oldScore: currentScore, + newScore, + sessionType: realSecurityData.sessionType + }); + } + } else if (window.DEBUG_MODE) { + console.log("\u2139\uFE0F Security level unchanged, skipping update"); + } + } else { + console.warn("\u26A0\uFE0F Security calculation returned invalid data"); + } + } catch (error) { + console.error("\u274C Error in real security calculation:", error); + } finally { + isUpdating = false; + } + }; + if (isConnected) { + updateRealSecurityStatus(); + if (!realSecurityLevel || realSecurityLevel.score < 50) { + const retryInterval = setInterval(() => { + if (!realSecurityLevel || realSecurityLevel.score < 50) { + updateRealSecurityStatus(); + } else { + clearInterval(retryInterval); + } + }, 5e3); + setTimeout(() => clearInterval(retryInterval), 3e4); + } + } + const interval = setInterval(updateRealSecurityStatus, 3e4); + return () => clearInterval(interval); + }, [webrtcManager, isConnected, lastSecurityUpdate, realSecurityLevel]); + React.useEffect(() => { + const handleSecurityUpdate = (event) => { + if (window.DEBUG_MODE) { + console.log("\u{1F512} Security level update event received:", event.detail); + } + setTimeout(() => { + setLastSecurityUpdate(0); + }, 100); + }; + const handleRealSecurityCalculated = (event) => { + if (window.DEBUG_MODE) { + console.log("\u{1F510} Real security calculated event:", event.detail); + } + if (event.detail && event.detail.securityData) { + setRealSecurityLevel(event.detail.securityData); + setLastSecurityUpdate(Date.now()); + } + }; + document.addEventListener("security-level-updated", handleSecurityUpdate); + document.addEventListener("real-security-calculated", handleRealSecurityCalculated); + window.forceHeaderSecurityUpdate = (webrtcManager2) => { + if (window.DEBUG_MODE) { + console.log("\u{1F504} Force header security update called"); + } + if (webrtcManager2 && window.EnhancedSecureCryptoUtils) { + window.EnhancedSecureCryptoUtils.calculateSecurityLevel(webrtcManager2).then((securityData) => { + if (securityData && securityData.isRealData !== false) { + setRealSecurityLevel(securityData); + setLastSecurityUpdate(Date.now()); + console.log("\u2705 Header security level force-updated"); + } + }).catch((error) => { + console.error("\u274C Force update failed:", error); + }); + } else { + setLastSecurityUpdate(0); + } + }; + return () => { + document.removeEventListener("security-level-updated", handleSecurityUpdate); + document.removeEventListener("real-security-calculated", handleRealSecurityCalculated); + }; + }, []); + React.useEffect(() => { + const updateSessionInfo = () => { + if (sessionManager) { + const isActive = sessionManager.hasActiveSession(); + const timeLeft = sessionManager.getTimeLeft(); + const currentSession = sessionManager.currentSession; + setHasActiveSession(isActive); + setCurrentTimeLeft(timeLeft); + setSessionType(currentSession?.type || "unknown"); + } + }; + updateSessionInfo(); + const interval = setInterval(updateSessionInfo, 1e3); + return () => clearInterval(interval); + }, [sessionManager]); + React.useEffect(() => { + if (sessionManager?.hasActiveSession()) { + setCurrentTimeLeft(sessionManager.getTimeLeft()); + setHasActiveSession(true); + } else { + setHasActiveSession(false); + setRealSecurityLevel(null); + setLastSecurityUpdate(0); + setSessionType("unknown"); + } + }, [sessionManager, sessionTimeLeft]); + React.useEffect(() => { + const handleForceUpdate = (event) => { + if (sessionManager) { + const isActive = sessionManager.hasActiveSession(); + const timeLeft = sessionManager.getTimeLeft(); + const currentSession = sessionManager.currentSession; + setHasActiveSession(isActive); + setCurrentTimeLeft(timeLeft); + setSessionType(currentSession?.type || "unknown"); + } + }; + const handleConnectionCleaned = () => { + if (window.DEBUG_MODE) { + console.log("\u{1F9F9} Connection cleaned - clearing security data in header"); + } + setRealSecurityLevel(null); + setLastSecurityUpdate(0); + setHasActiveSession(false); + setCurrentTimeLeft(0); + setSessionType("unknown"); + }; + const handlePeerDisconnect = () => { + if (window.DEBUG_MODE) { + console.log("\u{1F44B} Peer disconnect detected - clearing security data in header"); + } + setRealSecurityLevel(null); + setLastSecurityUpdate(0); + }; + document.addEventListener("force-header-update", handleForceUpdate); + document.addEventListener("peer-disconnect", handlePeerDisconnect); + document.addEventListener("connection-cleaned", handleConnectionCleaned); + return () => { + document.removeEventListener("force-header-update", handleForceUpdate); + document.removeEventListener("peer-disconnect", handlePeerDisconnect); + document.removeEventListener("connection-cleaned", handleConnectionCleaned); + }; + }, [sessionManager]); + const handleSecurityClick = (event) => { + if (event && (event.button === 2 || event.ctrlKey || event.metaKey)) { + if (onDisconnect && typeof onDisconnect === "function") { + onDisconnect(); + return; + } + } + if (!realSecurityLevel) { + alert("Security verification in progress...\nPlease wait for real-time cryptographic verification to complete."); + return; + } + let message = `\u{1F512} REAL-TIME SECURITY VERIFICATION + +`; + message += `Security Level: ${realSecurityLevel.level} (${realSecurityLevel.score}%) +`; + message += `Session Type: ${realSecurityLevel.sessionType || "demo"} +`; + message += `Verification Time: ${new Date(realSecurityLevel.timestamp).toLocaleTimeString()} +`; + message += `Data Source: ${realSecurityLevel.isRealData ? "Real Cryptographic Tests" : "Simulated Data"} + +`; + if (realSecurityLevel.verificationResults) { + message += "DETAILED CRYPTOGRAPHIC TESTS:\n"; + message += "=" + "=".repeat(40) + "\n"; + const passedTests = Object.entries(realSecurityLevel.verificationResults).filter(([key, result]) => result.passed); + const failedTests = Object.entries(realSecurityLevel.verificationResults).filter(([key, result]) => !result.passed); + if (passedTests.length > 0) { + message += "\u2705 PASSED TESTS:\n"; + passedTests.forEach(([key, result]) => { + const testName = key.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase()); + message += ` ${testName}: ${result.details} +`; + }); + message += "\n"; + } + if (failedTests.length > 0) { + message += "\u274C UNAVAILABLE/Failed TESTS:\n"; + failedTests.forEach(([key, result]) => { + const testName = key.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase()); + message += ` ${testName}: ${result.details} +`; + }); + message += "\n"; + } + message += `SUMMARY: +`; + message += `Passed: ${realSecurityLevel.passedChecks}/${realSecurityLevel.totalChecks} tests +`; + } + message += ` +\u{1F4CB} WHAT'S AVAILABLE IN OTHER SESSIONS: +`; + message += "=" + "=".repeat(40) + "\n"; + if (realSecurityLevel.sessionType === "demo") { + message += `\u{1F512} BASIC SESSION (5,000 sat - $2.00): +`; + message += ` \u2022 ECDSA Digital Signatures +`; + message += ` \u2022 Metadata Protection +`; + message += ` \u2022 Perfect Forward Secrecy +`; + message += ` \u2022 Nested Encryption +`; + message += ` \u2022 Packet Padding + +`; + message += `\u{1F680} PREMIUM SESSION (20,000 sat - $8.00): +`; + message += ` \u2022 All Basic + Enhanced features +`; + message += ` \u2022 Traffic Obfuscation +`; + message += ` \u2022 Fake Traffic Generation +`; + message += ` \u2022 Decoy Channels +`; + message += ` \u2022 Anti-Fingerprinting +`; + message += ` \u2022 Message Chunking +`; + message += ` \u2022 Advanced Replay Protection +`; + } else if (realSecurityLevel.sessionType === "basic") { + message += `\u{1F680} PREMIUM SESSION (20,000 sat - $8.00): +`; + message += ` \u2022 Traffic Obfuscation +`; + message += ` \u2022 Fake Traffic Generation +`; + message += ` \u2022 Decoy Channels +`; + message += ` \u2022 Anti-Fingerprinting +`; + message += ` \u2022 Message Chunking +`; + message += ` \u2022 Advanced Replay Protection +`; + } + message += ` +${realSecurityLevel.details || "Real cryptographic verification completed"}`; + if (realSecurityLevel.isRealData) { + message += "\n\n\u2705 This is REAL-TIME verification using actual cryptographic functions."; + } else { + message += "\n\n\u26A0\uFE0F Warning: This data may be simulated. Connection may not be fully established."; + } + alert(message); + }; + const getStatusConfig = () => { + switch (status) { + case "connected": + return { + text: "Connected", + className: "status-connected", + badgeClass: "bg-green-500/10 text-green-400 border-green-500/20" + }; + case "verifying": + return { + text: "Verifying...", + className: "status-verifying", + badgeClass: "bg-purple-500/10 text-purple-400 border-purple-500/20" + }; + case "connecting": + return { + text: "Connecting...", + className: "status-connecting", + badgeClass: "bg-blue-500/10 text-blue-400 border-blue-500/20" + }; + case "retrying": + return { + text: "Retrying...", + className: "status-connecting", + badgeClass: "bg-yellow-500/10 text-yellow-400 border-yellow-500/20" + }; + case "failed": + return { + text: "Error", + className: "status-failed", + badgeClass: "bg-red-500/10 text-red-400 border-red-500/20" + }; + case "reconnecting": + return { + text: "Reconnecting...", + className: "status-connecting", + badgeClass: "bg-yellow-500/10 text-yellow-400 border-yellow-500/20" + }; + case "peer_disconnected": + return { + text: "Peer disconnected", + className: "status-failed", + badgeClass: "bg-orange-500/10 text-orange-400 border-orange-500/20" + }; + default: + return { + text: "Not connected", + className: "status-disconnected", + badgeClass: "bg-gray-500/10 text-gray-400 border-gray-500/20" + }; + } + }; + const config = getStatusConfig(); + const displaySecurityLevel = realSecurityLevel || securityLevel; + const shouldShowTimer = hasActiveSession && currentTimeLeft > 0 && window.SessionTimer; + const getSecurityIndicatorDetails = () => { + if (!displaySecurityLevel) { + return { + tooltip: "Security verification in progress...", + isVerified: false, + dataSource: "loading" + }; + } + const isRealData = displaySecurityLevel.isRealData !== false; + const baseTooltip = `${displaySecurityLevel.level} (${displaySecurityLevel.score}%)`; + if (isRealData) { + return { + tooltip: `${baseTooltip} - Real-time verification \u2705 +Right-click or Ctrl+click to disconnect`, + isVerified: true, + dataSource: "real" + }; + } else { + return { + tooltip: `${baseTooltip} - Estimated (connection establishing...) +Right-click or Ctrl+click to disconnect`, + isVerified: false, + dataSource: "estimated" + }; + } + }; + const securityDetails = getSecurityIndicatorDetails(); + React.useEffect(() => { + window.debugHeaderSecurity = () => { + console.log("\u{1F50D} Header Security Debug:", { + realSecurityLevel, + lastSecurityUpdate, + isConnected, + webrtcManagerProp: !!webrtcManager, + windowWebrtcManager: !!window.webrtcManager, + cryptoUtils: !!window.EnhancedSecureCryptoUtils, + displaySecurityLevel, + securityDetails + }); + }; + return () => { + delete window.debugHeaderSecurity; + }; + }, [realSecurityLevel, lastSecurityUpdate, isConnected, webrtcManager, displaySecurityLevel, securityDetails]); + return React.createElement("header", { + className: "header-minimal sticky top-0 z-50" + }, [ + React.createElement("div", { + key: "container", + className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8" + }, [ + React.createElement("div", { + key: "content", + className: "flex items-center justify-between h-16" + }, [ + // Logo and Title + React.createElement("div", { + key: "logo-section", + className: "flex items-center space-x-2 sm:space-x-3" + }, [ + React.createElement("div", { + key: "logo", + className: "icon-container w-8 h-8 sm:w-10 sm:h-10" + }, [ + React.createElement("i", { + className: "fas fa-shield-halved accent-orange text-sm sm:text-base" + }) + ]), + React.createElement("div", { + key: "title-section" + }, [ + React.createElement("h1", { + key: "title", + className: "text-lg sm:text-xl font-semibold text-primary" + }, "SecureBit.chat"), + React.createElement("p", { + key: "subtitle", + className: "text-xs sm:text-sm text-muted hidden sm:block" + }, "End-to-end freedom v4.02.985") + ]) + ]), + // Status and Controls - Responsive + React.createElement("div", { + key: "status-section", + className: "flex items-center space-x-2 sm:space-x-3" + }, [ + // Session Timer + shouldShowTimer && React.createElement(window.SessionTimer, { + key: "session-timer", + timeLeft: currentTimeLeft, + sessionType, + sessionManager, + onDisconnect + }), + displaySecurityLevel && React.createElement("div", { + key: "security-level", + className: "hidden md:flex items-center space-x-2 cursor-pointer hover:opacity-80 transition-opacity duration-200", + onClick: handleSecurityClick, + onContextMenu: (e) => { + e.preventDefault(); + if (onDisconnect && typeof onDisconnect === "function") { + onDisconnect(); + } + }, + title: securityDetails.tooltip + }, [ + React.createElement("div", { + key: "security-icon", + className: `w-6 h-6 rounded-full flex items-center justify-center relative ${displaySecurityLevel.color === "green" ? "bg-green-500/20" : displaySecurityLevel.color === "orange" ? "bg-orange-500/20" : displaySecurityLevel.color === "yellow" ? "bg-yellow-500/20" : "bg-red-500/20"} ${securityDetails.isVerified ? "" : "animate-pulse"}` + }, [ + React.createElement("i", { + className: `fas fa-shield-alt text-xs ${displaySecurityLevel.color === "green" ? "text-green-400" : displaySecurityLevel.color === "orange" ? "text-orange-400" : displaySecurityLevel.color === "yellow" ? "text-yellow-400" : "text-red-400"}` + }) + ]), + React.createElement("div", { + key: "security-info", + className: "flex flex-col" + }, [ + React.createElement("div", { + key: "security-level-text", + className: "text-xs font-medium text-primary flex items-center space-x-1" + }, [ + React.createElement("span", {}, `${displaySecurityLevel.level} (${displaySecurityLevel.score}%)`) + ]), + React.createElement( + "div", + { + key: "security-details", + className: "text-xs text-muted mt-1 hidden lg:block" + }, + securityDetails.dataSource === "real" ? `${displaySecurityLevel.passedChecks || 0}/${displaySecurityLevel.totalChecks || 0} tests` : displaySecurityLevel.details || `Stage ${displaySecurityLevel.stage || 1}` + ), + React.createElement("div", { + key: "security-progress", + className: "w-16 h-1 bg-gray-600 rounded-full overflow-hidden" + }, [ + React.createElement("div", { + key: "progress-bar", + className: `h-full transition-all duration-500 ${displaySecurityLevel.color === "green" ? "bg-green-400" : displaySecurityLevel.color === "orange" ? "bg-orange-400" : displaySecurityLevel.color === "yellow" ? "bg-yellow-400" : "bg-red-400"}`, + style: { width: `${displaySecurityLevel.score}%` } + }) + ]) + ]) + ]), + // Mobile Security Indicator + displaySecurityLevel && React.createElement("div", { + key: "mobile-security", + className: "md:hidden flex items-center" + }, [ + React.createElement("div", { + key: "mobile-security-icon", + className: `w-8 h-8 rounded-full flex items-center justify-center cursor-pointer hover:opacity-80 transition-opacity duration-200 relative ${displaySecurityLevel.color === "green" ? "bg-green-500/20" : displaySecurityLevel.color === "orange" ? "bg-orange-500/20" : displaySecurityLevel.color === "yellow" ? "bg-yellow-500/20" : "bg-red-500/20"} ${securityDetails.isVerified ? "" : "animate-pulse"}`, + title: securityDetails.tooltip, + onClick: handleSecurityClick, + onContextMenu: (e) => { + e.preventDefault(); + if (onDisconnect && typeof onDisconnect === "function") { + onDisconnect(); + } + } + }, [ + React.createElement("i", { + className: `fas fa-shield-alt text-sm ${displaySecurityLevel.color === "green" ? "text-green-400" : displaySecurityLevel.color === "orange" ? "text-orange-400" : displaySecurityLevel.color === "yellow" ? "text-yellow-400" : "text-red-400"}` + }) + ]) + ]), + // Status Badge + React.createElement("div", { + key: "status-badge", + className: `px-2 sm:px-3 py-1.5 rounded-lg border ${config.badgeClass} flex items-center space-x-1 sm:space-x-2` + }, [ + React.createElement("span", { + key: "status-dot", + className: `status-dot ${config.className}` + }), + React.createElement("span", { + key: "status-text", + className: "text-xs sm:text-sm font-medium" + }, config.text) + ]), + // Disconnect Button + isConnected && React.createElement("button", { + key: "disconnect-btn", + onClick: onDisconnect, + className: "p-1.5 sm:px-3 sm:py-1.5 bg-red-500/10 hover:bg-red-500/20 text-red-400 border border-red-500/20 rounded-lg transition-all duration-200 text-sm" + }, [ + React.createElement("i", { + className: "fas fa-power-off sm:mr-2" + }), + React.createElement("span", { + className: "hidden sm:inline" + }, "Disconnect") + ]) + ]) + ]) + ]) + ]); +}; +window.EnhancedMinimalHeader = EnhancedMinimalHeader; + +// src/components/ui/SessionTypeSelector.jsx +var SessionTypeSelector = ({ onSelectType, onCancel, sessionManager }) => { + const [selectedType, setSelectedType] = React.useState(null); + const [demoInfo, setDemoInfo] = React.useState(null); + const [refreshTimer, setRefreshTimer] = React.useState(null); + const [lastRefresh, setLastRefresh] = React.useState(Date.now()); + const updateDemoInfo = React.useCallback(() => { + if (sessionManager && sessionManager.getDemoSessionInfo) { + try { + const info = sessionManager.getDemoSessionInfo(); + if (window.DEBUG_MODE) { + console.log("\u{1F504} Demo info updated:", info); + } + setDemoInfo(info); + setLastRefresh(Date.now()); + } catch (error) { + console.error("Failed to get demo info:", error); + } + } + }, [sessionManager]); + React.useEffect(() => { + updateDemoInfo(); + const interval = setInterval(updateDemoInfo, 1e4); + setRefreshTimer(interval); + return () => { + if (interval) clearInterval(interval); + }; + }, [updateDemoInfo]); + React.useEffect(() => { + return () => { + if (refreshTimer) { + clearInterval(refreshTimer); + } + }; + }, [refreshTimer]); + const sessionTypes = [ + { + id: "demo", + name: "Demo", + duration: "6 minutes", + price: "0 sat", + usd: "$0.00", + popular: false, + securityLevel: "Basic", + securityBadge: "BASIC", + securityColor: "bg-blue-500/20 text-blue-300", + description: "Limited testing session with basic security", + features: [ + "Basic end-to-end encryption", + "Simple key exchange", + "Message integrity", + "Rate limiting" + ], + limitations: [ + "No advanced security features", + "No traffic obfuscation", + "No metadata protection" + ] + }, + { + id: "basic", + name: "Basic", + duration: "1 hour", + price: "5,000 sat", + usd: "$2.00", + securityLevel: "Enhanced", + securityBadge: "ENHANCED", + securityColor: "bg-orange-500/20 text-orange-300", + popular: true, + description: "Full featured session with enhanced security", + features: [ + "All basic features", + "ECDSA digital signatures", + "Metadata protection", + "Perfect forward secrecy", + "Nested encryption", + "Packet padding", + "Complete ASN.1 validation", + "OID and EC point verification", + "SPKI structure validation", + "18-layer security architecture", + "ASN.1 Validated" + ], + limitations: [ + "Limited traffic obfuscation", + "No fake traffic generation" + ] + }, + { + id: "premium", + name: "Premium", + duration: "6 hours", + price: "20,000 sat", + usd: "$8.00", + securityLevel: "Maximum", + securityBadge: "MAXIMUM", + securityColor: "bg-green-500/20 text-green-300", + description: "Extended session with maximum security protection", + features: [ + "All enhanced features", + "Traffic obfuscation", + "Fake traffic generation", + "Decoy channels", + "Anti-fingerprinting", + "Message chunking", + "Advanced replay protection", + "Complete ASN.1 validation", + "OID and EC point verification", + "SPKI structure validation", + "18-layer security architecture", + "ASN.1 Validated" + ], + limitations: [] + } + ]; + const handleTypeSelect = (typeId) => { + console.log(`\u{1F3AF} Selecting session type: ${typeId}`); + if (typeId === "demo") { + if (demoInfo && !demoInfo.canUseNow) { + let message = `Demo session not available. + +`; + if (demoInfo.blockingReason === "global_limit") { + message += `Reason: Too many global demo sessions active (${demoInfo.globalActive}/${demoInfo.globalLimit}) +`; + message += `Please try again in a few minutes.`; + } else if (demoInfo.blockingReason === "daily_limit") { + message += `Reason: Daily limit reached (${demoInfo.used}/${demoInfo.total}) +`; + message += `Next available: ${demoInfo.nextAvailable}`; + } else if (demoInfo.blockingReason === "session_cooldown") { + message += `Reason: Cooldown between sessions +`; + message += `Next available: ${demoInfo.nextAvailable}`; + } else if (demoInfo.blockingReason === "completion_cooldown") { + message += `Reason: Wait period after last session +`; + message += `Next available: ${demoInfo.nextAvailable}`; + } else { + message += `Next available: ${demoInfo.nextAvailable}`; + } + alert(message); + return; + } + } + setSelectedType(typeId); + }; + const formatCooldownTime = (minutes) => { + if (minutes >= 60) { + const hours = Math.floor(minutes / 60); + const remainingMinutes = minutes % 60; + return `${hours}h ${remainingMinutes}m`; + } + return `${minutes}m`; + }; + return React.createElement("div", { className: "space-y-6" }, [ + React.createElement("div", { key: "header", className: "text-center" }, [ + React.createElement("h3", { + key: "title", + className: "text-xl font-semibold text-white mb-2" + }, "Choose Your Session"), + React.createElement("p", { + key: "subtitle", + className: "text-gray-300 text-sm" + }, "Different security levels for different needs") + ]), + React.createElement( + "div", + { key: "types", className: "space-y-4" }, + sessionTypes.map((type) => { + const isDemo = type.id === "demo"; + const isDisabled = isDemo && demoInfo && !demoInfo.canUseNow; + return React.createElement("div", { + key: type.id, + onClick: () => !isDisabled && handleTypeSelect(type.id), + className: `relative card-minimal ${selectedType === type.id ? "card-minimal--selected" : ""} rounded-lg p-5 border-2 transition-all ${selectedType === type.id ? "border-orange-500 bg-orange-500/15 ring-2 ring-orange-400 ring-offset-2 ring-offset-black/30" : "border-gray-600 hover:border-orange-400"} ${type.popular && selectedType !== type.id ? "ring-2 ring-orange-500/30" : ""} ${isDisabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}` + }, [ + // Popular badge + type.popular && React.createElement("div", { + key: "popular-badge", + className: "absolute -top-2 right-3 bg-orange-500 text-white text-xs px-3 py-1 rounded-full font-medium" + }, "Most Popular"), + React.createElement("div", { key: "content", className: "space-y-4" }, [ + // Header with name and security level + React.createElement("div", { key: "header", className: "flex items-start justify-between" }, [ + React.createElement("div", { key: "title-section" }, [ + React.createElement("div", { key: "name-row", className: "flex items-center gap-3 mb-2" }, [ + React.createElement("h4", { + key: "name", + className: "text-xl font-bold text-white" + }, type.name), + isDemo && React.createElement("span", { + key: "free-badge", + className: "text-xs bg-blue-500/20 text-blue-300 px-2 py-1 rounded-full font-medium" + }, "FREE"), + React.createElement("span", { + key: "security-badge", + className: `text-xs px-2 py-1 rounded-full font-medium ${type.securityColor}` + }, type.securityBadge) + ]), + React.createElement("p", { + key: "duration", + className: "text-gray-300 font-medium mb-1" + }, `Duration: ${type.duration}`), + React.createElement("p", { + key: "description", + className: "text-sm text-gray-400" + }, type.description) + ]), + React.createElement("div", { key: "pricing", className: "text-right" }, [ + React.createElement("div", { + key: "sats", + className: `text-xl font-bold ${isDemo ? "text-green-400" : "text-orange-400"}` + }, type.price), + React.createElement("div", { + key: "usd", + className: "text-sm text-gray-400" + }, type.usd) + ]) + ]), + // Demo status info + isDemo && demoInfo && React.createElement("div", { + key: "demo-status", + className: "p-3 bg-blue-900/20 border border-blue-700/30 rounded-lg" + }, [ + React.createElement( + "div", + { + key: "availability", + className: `text-sm font-medium ${demoInfo.canUseNow ? "text-green-400" : "text-yellow-400"}` + }, + demoInfo.canUseNow ? `\u2705 Available (${demoInfo.available}/${demoInfo.total} today)` : `\u23F0 Next: ${demoInfo.nextAvailable}` + ), + demoInfo.globalActive > 0 && React.createElement("div", { + key: "global-status", + className: "text-blue-300 text-xs mt-1" + }, `\u{1F310} Global: ${demoInfo.globalActive}/${demoInfo.globalLimit} active`) + ]), + // Security features + React.createElement("div", { key: "features-section", className: "space-y-3" }, [ + React.createElement("div", { key: "features" }, [ + React.createElement("h5", { + key: "features-title", + className: "text-sm font-medium text-green-300 mb-2 flex items-center" + }, [ + React.createElement("i", { + key: "shield-icon", + className: "fas fa-shield-alt mr-2" + }), + "Security Features" + ]), + React.createElement("div", { + key: "features-list", + className: "grid grid-cols-1 gap-1" + }, type.features.map( + (feature, index) => React.createElement("div", { + key: index, + className: "flex items-center gap-2 text-xs text-gray-300" + }, [ + React.createElement("i", { + key: "check", + className: "fas fa-check text-green-400 w-3" + }), + React.createElement("span", { + key: "text" + }, feature) + ]) + )) + ]), + // Limitations (if any) + type.limitations && type.limitations.length > 0 && React.createElement("div", { key: "limitations" }, [ + React.createElement("h5", { + key: "limitations-title", + className: "text-sm font-medium text-yellow-300 mb-2 flex items-center" + }, [ + React.createElement("i", { + key: "info-icon", + className: "fas fa-info-circle mr-2" + }), + "Limitations" + ]), + React.createElement("div", { + key: "limitations-list", + className: "grid grid-cols-1 gap-1" + }, type.limitations.map( + (limitation, index) => React.createElement("div", { + key: index, + className: "flex items-center gap-2 text-xs text-gray-400" + }, [ + React.createElement("i", { + key: "minus", + className: "fas fa-minus text-yellow-400 w-3" + }), + React.createElement("span", { + key: "text" + }, limitation) + ]) + )) + ]) + ]) + ]) + ]); + }) + ), + demoInfo && React.createElement("div", { + key: "demo-info", + className: "bg-gradient-to-r from-blue-900/20 to-purple-900/20 border border-blue-700/50 rounded-lg p-4" + }, [ + React.createElement("div", { + key: "demo-header", + className: "flex items-center gap-2 text-blue-300 text-sm font-medium mb-3" + }, [ + React.createElement("i", { + key: "icon", + className: "fas fa-info-circle" + }), + React.createElement("span", { + key: "title" + }, "Demo Session Information") + ]), + React.createElement("div", { + key: "demo-details", + className: "grid grid-cols-1 md:grid-cols-2 gap-3 text-blue-200 text-xs" + }, [ + React.createElement("div", { key: "limits", className: "space-y-1" }, [ + React.createElement("div", { key: "daily" }, `\u{1F4C5} Daily limit: ${demoInfo.total} sessions`), + React.createElement("div", { key: "duration" }, `\u23F1\uFE0F Duration: ${demoInfo.durationMinutes} minutes each`), + React.createElement("div", { key: "cooldown" }, `\u23F0 Cooldown: ${demoInfo.sessionCooldownMinutes} min between sessions`) + ]), + React.createElement("div", { key: "status", className: "space-y-1" }, [ + React.createElement("div", { key: "used" }, `\u{1F4CA} Used today: ${demoInfo.used}/${demoInfo.total}`), + React.createElement("div", { key: "global" }, `\u{1F310} Global active: ${demoInfo.globalActive}/${demoInfo.globalLimit}`), + React.createElement("div", { + key: "next", + className: demoInfo.canUseNow ? "text-green-300" : "text-yellow-300" + }, `\u{1F3AF} Status: ${demoInfo.canUseNow ? "Available now" : demoInfo.nextAvailable}`) + ]) + ]), + React.createElement("div", { + key: "security-note", + className: "mt-3 p-2 bg-yellow-500/10 border border-yellow-500/20 rounded text-yellow-200 text-xs" + }, "\u26A0\uFE0F Demo sessions use basic security only. Upgrade to paid sessions for enhanced protection."), + React.createElement("div", { + key: "last-updated", + className: "text-xs text-gray-400 mt-2 text-center" + }, `Last updated: ${new Date(lastRefresh).toLocaleTimeString()}`) + ]), + // Action buttons + React.createElement("div", { key: "buttons", className: "flex space-x-3" }, [ + React.createElement("button", { + key: "continue", + onClick: () => { + if (selectedType) { + console.log(`\u{1F680} Proceeding with session type: ${selectedType}`); + onSelectType(selectedType); + } + }, + disabled: !selectedType || selectedType === "demo" && demoInfo && !demoInfo.canUseNow, + className: "flex-1 lightning-button text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50 disabled:cursor-not-allowed transition-all" + }, [ + React.createElement("i", { + key: "icon", + className: selectedType === "demo" ? "fas fa-play mr-2" : "fas fa-bolt mr-2" + }), + selectedType === "demo" ? "Start Demo Session" : "Continue to Payment" + ]), + React.createElement("button", { + key: "cancel", + onClick: onCancel, + className: "px-6 py-3 bg-gray-600 hover:bg-gray-500 text-white rounded-lg transition-all" + }, "Cancel") + ]) + ]); +}; +window.SessionTypeSelector = SessionTypeSelector; + +// src/components/ui/LightningPayment.jsx +var React2 = window.React; +var { useState, useEffect } = React2; +var IntegratedLightningPayment = ({ sessionType, onSuccess, onCancel, paymentManager }) => { + const [paymentMethod, setPaymentMethod] = useState("webln"); + const [preimage, setPreimage] = useState(""); + const [isProcessing, setIsProcessing] = useState(false); + const [error, setError] = useState(""); + const [invoice, setInvoice] = useState(null); + const [paymentStatus, setPaymentStatus] = useState("pending"); + const [qrCodeUrl, setQrCodeUrl] = useState(""); + useEffect(() => { + createInvoice(); + }, [sessionType]); + const createInvoice = async () => { + if (sessionType === "free") { + setPaymentStatus("free"); + return; + } + setIsProcessing(true); + setError(""); + try { + if (!paymentManager) { + throw new Error("Payment manager not available. Please check sessionManager initialization."); + } + const createdInvoice = await paymentManager.createLightningInvoice(sessionType); + if (!createdInvoice) { + throw new Error("Failed to create invoice"); + } + setInvoice(createdInvoice); + setPaymentStatus("created"); + if (createdInvoice.paymentRequest) { + try { + const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300, margin: 2, errorCorrectionLevel: "M" }); + setQrCodeUrl(dataUrl); + } catch (e) { + console.warn("QR local generation failed, showing placeholder"); + const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300 }); + setQrCodeUrl(dataUrl); + } + } + } catch (err) { + console.error("Invoice creation failed:", err); + setError(`Error creating invoice: ${err.message}`); + } finally { + setIsProcessing(false); + } + }; + const handleWebLNPayment = async () => { + if (!window.webln) { + setError("WebLN is not supported. Please use the Alby or Zeus wallet. SecureBit.chat v4.02.442 - ASN.1 Validated requires WebLN for Lightning payments."); + return; + } + if (!invoice || !invoice.paymentRequest) { + setError("Invoice is not ready for payment"); + return; + } + setIsProcessing(true); + setError(""); + try { + await window.webln.enable(); + const result = await window.webln.sendPayment(invoice.paymentRequest); + if (result.preimage) { + setPaymentStatus("paid"); + await activateSession(result.preimage); + } else { + setError("Payment does not contain preimage"); + } + } catch (err) { + console.error("WebLN payment failed:", err); + setError(`WebLN Error: ${err.message}`); + } finally { + setIsProcessing(false); + } + }; + const handleManualVerification = async () => { + const trimmedPreimage = preimage.trim(); + if (!trimmedPreimage) { + setError("Enter payment preimage"); + return; + } + if (trimmedPreimage.length !== 64) { + setError("The preimage must be exactly 64 characters long."); + return; + } + if (!/^[0-9a-fA-F]{64}$/.test(trimmedPreimage)) { + setError("The preimage must contain only hexadecimal characters (0-9, a-f, A-F)."); + return; + } + if (trimmedPreimage === "1".repeat(64) || trimmedPreimage === "a".repeat(64) || trimmedPreimage === "f".repeat(64)) { + setError("The entered preimage is too weak. Please verify the key.."); + return; + } + setError(""); + setIsProcessing(true); + try { + await activateSession(trimmedPreimage); + } catch (err) { + setError(`Activation error: ${err.message}`); + } finally { + setIsProcessing(false); + } + }; + const activateSession = async (preimageValue) => { + try { + let result; + if (paymentManager) { + const paymentHash = invoice?.paymentHash || "dummy_hash"; + result = await paymentManager.safeActivateSession(sessionType, preimageValue, paymentHash); + } else { + console.warn("Payment manager not available, using fallback"); + result = { success: true, method: "fallback" }; + } + if (result.success) { + setPaymentStatus("paid"); + onSuccess(preimageValue, invoice); + } else { + console.error("\u274C Session activation failed:", result); + throw new Error(`Session activation failed: ${result.reason}`); + } + } catch (err) { + console.error("\u274C Session activation failed:", err); + throw err; + } + }; + const handleFreeSession = async () => { + setIsProcessing(true); + try { + await activateSession("0".repeat(64)); + } catch (err) { + setError(`Free session activation error: ${err.message}`); + } finally { + setIsProcessing(false); + } + }; + const copyToClipboard = (text) => { + navigator.clipboard.writeText(text).then(() => { + }); + }; + const pricing = { + free: { sats: 1, hours: 1 / 60 }, + basic: { sats: 500, hours: 1 }, + premium: { sats: 1e3, hours: 4 }, + extended: { sats: 2e3, hours: 24 } + }[sessionType]; + return React2.createElement("div", { className: "space-y-4 max-w-md mx-auto" }, [ + React2.createElement("div", { key: "header", className: "text-center" }, [ + React2.createElement("h3", { + key: "title", + className: "text-xl font-semibold text-white mb-2" + }, sessionType === "free" ? "Free session" : "Lightning payment"), + React2.createElement( + "div", + { + key: "amount", + className: "text-2xl font-bold text-orange-400" + }, + sessionType === "free" ? "0 sat per minute" : `${pricing.sats} \u0441\u0430\u0442 \u0437\u0430 ${pricing.hours}\u0447` + ), + sessionType !== "free" && React2.createElement("div", { + key: "usd", + className: "text-sm text-gray-400 mt-1" + }, `\u2248 $${(pricing.sats * 4e-4).toFixed(2)} USD`) + ]), + // Loading State + isProcessing && paymentStatus === "pending" && React2.createElement("div", { + key: "loading", + className: "text-center" + }, [ + React2.createElement("div", { + key: "spinner", + className: "text-orange-400" + }, [ + React2.createElement("i", { className: "fas fa-spinner fa-spin mr-2" }), + "Creating invoice..." + ]) + ]), + // Free Session + sessionType === "free" && React2.createElement("div", { + key: "free-session", + className: "space-y-3" + }, [ + React2.createElement("div", { + key: "info", + className: "p-3 bg-blue-500/10 border border-blue-500/20 rounded text-blue-300 text-sm" + }, "A free 1-minute session will be activated."), + React2.createElement("button", { + key: "start-btn", + onClick: handleFreeSession, + disabled: isProcessing, + className: "w-full bg-blue-600 hover:bg-blue-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50" + }, [ + React2.createElement("i", { + key: "icon", + className: `fas ${isProcessing ? "fa-spinner fa-spin" : "fa-play"} mr-2` + }), + isProcessing ? "Activation..." : "Start free session" + ]) + ]), + // Paid Sessions + sessionType !== "free" && paymentStatus === "created" && invoice && React2.createElement("div", { + key: "paid-session", + className: "space-y-4" + }, [ + // QR Code + qrCodeUrl && React2.createElement("div", { + key: "qr-section", + className: "text-center" + }, [ + React2.createElement("div", { + key: "qr-container", + className: "bg-white p-4 rounded-lg inline-block" + }, [ + React2.createElement("img", { + key: "qr-img", + src: qrCodeUrl, + alt: "Payment QR Code", + className: "w-48 h-48" + }) + ]), + React2.createElement("div", { + key: "qr-hint", + className: "text-xs text-gray-400 mt-2" + }, "Scan the QR code with any Lightning wallet") + ]), + // Payment Request + invoice.paymentRequest && React2.createElement("div", { + key: "payment-request", + className: "space-y-2" + }, [ + React2.createElement("div", { + key: "label", + className: "text-sm font-medium text-white" + }, "Payment Request:"), + React2.createElement("div", { + key: "request", + className: "p-3 bg-gray-800 rounded border text-xs font-mono text-gray-300 cursor-pointer hover:bg-gray-700", + onClick: () => copyToClipboard(invoice.paymentRequest) + }, [ + invoice.paymentRequest.substring(0, 50) + "...", + React2.createElement("i", { key: "copy-icon", className: "fas fa-copy ml-2 text-orange-400" }) + ]) + ]), + // WebLN Payment + React2.createElement("div", { + key: "webln-section", + className: "space-y-3" + }, [ + React2.createElement("h4", { + key: "webln-title", + className: "text-white font-medium flex items-center" + }, [ + React2.createElement("i", { key: "bolt-icon", className: "fas fa-bolt text-orange-400 mr-2" }), + "WebLN wallet (Alby, Zeus)" + ]), + React2.createElement("button", { + key: "webln-btn", + onClick: handleWebLNPayment, + disabled: isProcessing, + className: "w-full bg-orange-600 hover:bg-orange-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50" + }, [ + React2.createElement("i", { + key: "webln-icon", + className: `fas ${isProcessing ? "fa-spinner fa-spin" : "fa-bolt"} mr-2` + }), + isProcessing ? "Processing..." : "Pay via WebLN" + ]) + ]), + // Manual Payment + React2.createElement("div", { + key: "divider", + className: "text-center text-gray-400" + }, "or"), + React2.createElement("div", { + key: "manual-section", + className: "space-y-3" + }, [ + React2.createElement("h4", { + key: "manual-title", + className: "text-white font-medium" + }, "Manual payment verification"), + React2.createElement("input", { + key: "preimage-input", + type: "text", + value: preimage, + onChange: (e) => setPreimage(e.target.value), + placeholder: "Enter the preimage after payment...", + className: "w-full p-3 bg-gray-800 border border-gray-600 rounded text-white placeholder-gray-400 text-sm" + }), + React2.createElement("button", { + key: "verify-btn", + onClick: handleManualVerification, + disabled: isProcessing, + className: "w-full bg-green-600 hover:bg-green-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50" + }, [ + React2.createElement("i", { + key: "verify-icon", + className: `fas ${isProcessing ? "fa-spinner fa-spin" : "fa-check"} mr-2` + }), + isProcessing ? "Verification..." : "Confirm payment" + ]) + ]) + ]), + // Success State + paymentStatus === "paid" && React2.createElement("div", { + key: "success", + className: "text-center p-4 bg-green-500/10 border border-green-500/20 rounded" + }, [ + React2.createElement("i", { key: "success-icon", className: "fas fa-check-circle text-green-400 text-2xl mb-2" }), + React2.createElement("div", { key: "success-text", className: "text-green-300 font-medium" }, "Payment confirmed!"), + React2.createElement("div", { key: "success-subtext", className: "text-green-400 text-sm" }, "Session activated") + ]), + // Error State + error && React2.createElement("div", { + key: "error", + className: "p-3 bg-red-500/10 border border-red-500/20 rounded text-red-400 text-sm" + }, [ + React2.createElement("i", { key: "error-icon", className: "fas fa-exclamation-triangle mr-2" }), + error, + error.includes("invoice") && React2.createElement("button", { + key: "retry-btn", + onClick: createInvoice, + className: "ml-2 text-orange-400 hover:text-orange-300 underline" + }, "Try again") + ]), + // Cancel Button + React2.createElement("button", { + key: "cancel-btn", + onClick: onCancel, + className: "w-full bg-gray-600 hover:bg-gray-500 text-white py-2 px-4 rounded" + }, "Cancel") + ]); +}; +window.LightningPayment = IntegratedLightningPayment; + +// src/components/ui/PaymentModal.jsx +var React3 = window.React; +var { useState: useState2, useEffect: useEffect2, useRef } = React3; +var PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) => { + const [step, setStep] = React3.useState("select"); + const [selectedType, setSelectedType] = React3.useState(null); + const [invoice, setInvoice] = React3.useState(null); + const [paymentStatus, setPaymentStatus] = React3.useState("pending"); + const [error, setError] = React3.useState(""); + const [paymentMethod, setPaymentMethod] = React3.useState("webln"); + const [preimageInput, setPreimageInput] = React3.useState(""); + const [isProcessing, setIsProcessing] = React3.useState(false); + const [qrCodeUrl, setQrCodeUrl] = React3.useState(""); + const [paymentTimer, setPaymentTimer] = React3.useState(null); + const [timeLeft, setTimeLeft] = React3.useState(0); + const [showSecurityDetails, setShowSecurityDetails] = React3.useState(false); + const pollInterval = React3.useRef(null); + React3.useEffect(() => { + if (!isOpen) { + resetModal(); + if (pollInterval.current) { + clearInterval(pollInterval.current); + } + if (paymentTimer) { + clearInterval(paymentTimer); + } + } + }, [isOpen]); + const resetModal = () => { + setStep("select"); + setSelectedType(null); + setInvoice(null); + setPaymentStatus("pending"); + setError(""); + setPaymentMethod("webln"); + setPreimageInput(""); + setIsProcessing(false); + setQrCodeUrl(""); + setTimeLeft(0); + setShowSecurityDetails(false); + }; + const getSecurityFeaturesInfo = (sessionType) => { + const features = { + demo: { + title: "Demo Session - Basic Security", + description: "Limited testing session with basic security features", + available: [ + "\u{1F510} Basic end-to-end encryption (AES-GCM 256)", + "\u{1F511} Simple key exchange (ECDH P-384)", + "\u2705 Message integrity verification", + "\u26A1 Rate limiting protection" + ], + unavailable: [ + "\u{1F510} ECDSA Digital Signatures", + "\u{1F6E1}\uFE0F Metadata Protection", + "\u{1F504} Perfect Forward Secrecy", + "\u{1F510} Nested Encryption", + "\u{1F4E6} Packet Padding", + "\u{1F3AD} Traffic Obfuscation", + "\u{1F3AA} Fake Traffic Generation", + "\u{1F575}\uFE0F Decoy Channels", + "\u{1F6AB} Anti-Fingerprinting", + "\u{1F4DD} Message Chunking", + "\u{1F504} Advanced Replay Protection" + ], + upgrade: { + next: "Basic Session (5,000 sat - $2.00)", + features: [ + "\u{1F510} ECDSA Digital Signatures", + "\u{1F6E1}\uFE0F Metadata Protection", + "\u{1F504} Perfect Forward Secrecy", + "\u{1F510} Nested Encryption", + "\u{1F4E6} Packet Padding" + ] + } + }, + basic: { + title: "Basic Session - Enhanced Security", + description: "Full featured session with enhanced security features", + available: [ + "\u{1F510} Basic end-to-end encryption (AES-GCM 256)", + "\u{1F511} Simple key exchange (ECDH P-384)", + "\u2705 Message integrity verification", + "\u26A1 Rate limiting protection", + "\u{1F510} ECDSA Digital Signatures", + "\u{1F6E1}\uFE0F Metadata Protection", + "\u{1F504} Perfect Forward Secrecy", + "\u{1F510} Nested Encryption", + "\u{1F4E6} Packet Padding", + "\u{1F512} Complete ASN.1 validation", + "\u{1F50D} OID and EC point verification", + "\u{1F3D7}\uFE0F SPKI structure validation", + "\u{1F6E1}\uFE0F 18-layer security architecture" + ], + unavailable: [ + "\u{1F3AD} Traffic Obfuscation", + "\u{1F3AA} Fake Traffic Generation", + "\u{1F575}\uFE0F Decoy Channels", + "\u{1F6AB} Anti-Fingerprinting", + "\u{1F4DD} Message Chunking", + "\u{1F504} Advanced Replay Protection" + ], + upgrade: { + next: "Premium Session (20,000 sat - $8.00)", + features: [ + "\u{1F3AD} Traffic Obfuscation", + "\u{1F3AA} Fake Traffic Generation", + "\u{1F575}\uFE0F Decoy Channels", + "\u{1F6AB} Anti-Fingerprinting", + "\u{1F4DD} Message Chunking", + "\u{1F504} Advanced Replay Protection" + ] + } + }, + premium: { + title: "Premium Session - Maximum Security", + description: "Extended session with maximum security protection", + available: [ + "\u{1F510} Basic end-to-end encryption (AES-GCM 256)", + "\u{1F511} Simple key exchange (ECDH P-384)", + "\u2705 Message integrity verification", + "\u26A1 Rate limiting protection", + "\u{1F510} ECDSA Digital Signatures", + "\u{1F6E1}\uFE0F Metadata Protection", + "\u{1F504} Perfect Forward Secrecy", + "\u{1F510} Nested Encryption", + "\u{1F4E6} Packet Padding", + "\u{1F3AD} Traffic Obfuscation", + "\u{1F3AA} Fake Traffic Generation", + "\u{1F575}\uFE0F Decoy Channels", + "\u{1F6AB} Anti-Fingerprinting", + "\u{1F4DD} Message Chunking", + "\u{1F504} Advanced Replay Protection", + "\u{1F512} Complete ASN.1 validation", + "\u{1F50D} OID and EC point verification", + "\u{1F3D7}\uFE0F SPKI structure validation", + "\u{1F6E1}\uFE0F 18-layer security architecture", + "\u{1F680} ASN.1 Validated" + ], + unavailable: [], + upgrade: { + next: "Maximum security achieved!", + features: ["\u{1F389} All security features unlocked!"] + } + } + }; + return features[sessionType] || features.demo; + }; + const handleSelectType = async (type) => { + setSelectedType(type); + setError(""); + if (type === "demo") { + try { + if (!sessionManager || !sessionManager.createDemoSession) { + throw new Error("Demo session manager not available"); + } + const demoSession = sessionManager.createDemoSession(); + if (!demoSession.success) { + throw new Error(demoSession.reason); + } + setInvoice({ + sessionType: "demo", + amount: 0, + paymentHash: demoSession.paymentHash, + memo: `Demo session (${demoSession.durationMinutes} minutes)`, + createdAt: Date.now(), + isDemo: true, + preimage: demoSession.preimage, + warning: demoSession.warning, + securityLevel: "Basic" + }); + setPaymentStatus("demo"); + } catch (error2) { + setError(`Demo session creation failed: ${error2.message}`); + return; + } + } else { + await createRealInvoice(type); + } + setStep("payment"); + }; + const createRealInvoice = async (type) => { + setPaymentStatus("creating"); + setIsProcessing(true); + setError(""); + try { + console.log(`Creating Lightning invoice for ${type} session...`); + if (!sessionManager) { + throw new Error("Session manager not initialized"); + } + const createdInvoice = await sessionManager.createLightningInvoice(type); + if (!createdInvoice || !createdInvoice.paymentRequest) { + throw new Error("Failed to create Lightning invoice"); + } + createdInvoice.securityLevel = sessionManager.getSecurityLevelForSession(type); + setInvoice(createdInvoice); + setPaymentStatus("created"); + try { + const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300, margin: 2, errorCorrectionLevel: "M" }); + setQrCodeUrl(dataUrl); + } catch (e) { + console.warn("QR local generation failed, showing placeholder"); + const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300 }); + setQrCodeUrl(dataUrl); + } + const expirationTime = 15 * 60 * 1e3; + setTimeLeft(expirationTime); + const timer = setInterval(() => { + setTimeLeft((prev) => { + const newTime = prev - 1e3; + if (newTime <= 0) { + clearInterval(timer); + setPaymentStatus("expired"); + setError("Payment time has expired. Create a new invoice."); + return 0; + } + return newTime; + }); + }, 1e3); + setPaymentTimer(timer); + startPaymentPolling(createdInvoice.checkingId); + console.log("\u2705 Lightning invoice created successfully:", createdInvoice); + } catch (err) { + console.error("\u274C Invoice creation failed:", err); + setError(`Invoice creation error: ${err.message}`); + setPaymentStatus("failed"); + } finally { + setIsProcessing(false); + } + }; + const startPaymentPolling = (checkingId) => { + if (pollInterval.current) { + clearInterval(pollInterval.current); + } + pollInterval.current = setInterval(async () => { + try { + const status = await sessionManager.checkPaymentStatus(checkingId); + if (status.paid && status.preimage) { + clearInterval(pollInterval.current); + setPaymentStatus("paid"); + await handlePaymentSuccess(status.preimage); + } + } catch (error2) { + console.warn("Payment status check failed:", error2); + } + }, 3e3); + }; + const handleWebLNPayment = async () => { + if (!window.webln) { + setError("WebLN is not supported. Please install the Alby or Zeus wallet."); + return; + } + if (!invoice || !invoice.paymentRequest) { + setError("Invoice is not ready for payment."); + return; + } + setIsProcessing(true); + setError(""); + setPaymentStatus("paying"); + try { + await window.webln.enable(); + const result = await window.webln.sendPayment(invoice.paymentRequest); + if (result.preimage) { + setPaymentStatus("paid"); + await handlePaymentSuccess(result.preimage); + } else { + throw new Error("Payment does not contain preimage"); + } + } catch (err) { + console.error("\u274C WebLN payment failed:", err); + setError(`WebLN payment error: ${err.message}`); + setPaymentStatus("created"); + } finally { + setIsProcessing(false); + } + }; + const handleManualVerification = async () => { + const trimmedPreimage = preimageInput.trim(); + if (!trimmedPreimage) { + setError("Enter payment preimage"); + return; + } + if (trimmedPreimage.length !== 64) { + setError("The preimage must be exactly 64 characters long."); + return; + } + if (!/^[0-9a-fA-F]{64}$/.test(trimmedPreimage)) { + setError("The preimage must contain only hexadecimal characters (0-9, a-f, A-F)."); + return; + } + const dummyPreimages = ["1".repeat(64), "a".repeat(64), "f".repeat(64), "0".repeat(64)]; + if (dummyPreimages.includes(trimmedPreimage) && selectedType !== "demo") { + setError("The entered preimage is invalid. Please use the actual preimage from the payment."); + return; + } + setIsProcessing(true); + setError(""); + setPaymentStatus("paying"); + try { + await handlePaymentSuccess(trimmedPreimage); + } catch (err) { + setError(err.message); + setPaymentStatus("created"); + } finally { + setIsProcessing(false); + } + }; + const handleDemoSession = async () => { + setIsProcessing(true); + setError(""); + try { + if (!invoice?.preimage) { + throw new Error("Demo preimage not available"); + } + const isValid = await sessionManager.verifyPayment(invoice.preimage, invoice.paymentHash); + if (isValid && isValid.verified) { + onSessionPurchased({ + type: "demo", + preimage: invoice.preimage, + paymentHash: invoice.paymentHash, + amount: 0, + isDemo: true, + warning: invoice.warning, + securityLevel: "basic" + }); + setTimeout(() => { + onClose(); + }, 1500); + } else { + throw new Error(isValid?.reason || "Demo session verification failed"); + } + } catch (err) { + setError(`Demo session activation error: ${err.message}`); + } finally { + setIsProcessing(false); + } + }; + const handlePaymentSuccess = async (preimage) => { + try { + console.log("\u{1F50D} Verifying payment...", { selectedType, preimage }); + let isValid; + if (selectedType === "demo") { + return; + } else { + isValid = await sessionManager.verifyPayment(preimage, invoice.paymentHash); + } + if (isValid) { + if (pollInterval.current) { + clearInterval(pollInterval.current); + } + if (paymentTimer) { + clearInterval(paymentTimer); + } + onSessionPurchased({ + type: selectedType, + preimage, + paymentHash: invoice.paymentHash, + amount: invoice.amount, + securityLevel: invoice.securityLevel || (selectedType === "basic" ? "enhanced" : "maximum") + }); + setTimeout(() => { + onClose(); + }, 1500); + } else { + throw new Error("Payment verification failed. Please check the preimage for correctness or try again."); + } + } catch (error2) { + console.error("\u274C Payment verification failed:", error2); + throw error2; + } + }; + const copyToClipboard = async (text) => { + try { + await navigator.clipboard.writeText(text); + } catch (err) { + console.error("Failed to copy:", err); + } + }; + const formatTime = (ms) => { + const minutes = Math.floor(ms / 6e4); + const seconds = Math.floor(ms % 6e4 / 1e3); + return `${minutes}:${seconds.toString().padStart(2, "0")}`; + }; + const getSecurityBadgeColor = (level) => { + switch (level?.toLowerCase()) { + case "basic": + return "bg-blue-500/20 text-blue-300 border-blue-500/30"; + case "enhanced": + return "bg-orange-500/20 text-orange-300 border-orange-500/30"; + case "maximum": + return "bg-green-500/20 text-green-300 border-green-500/30"; + default: + return "bg-gray-500/20 text-gray-300 border-gray-500/30"; + } + }; + const pricing = sessionManager?.sessionPrices || { + demo: { sats: 0, hours: 0.1, usd: 0 }, + basic: { sats: 5e3, hours: 1, usd: 2 }, + premium: { sats: 2e4, hours: 6, usd: 8 } + }; + if (!isOpen) return null; + return React3.createElement("div", { + className: "fixed inset-0 bg-black/80 backdrop-blur-sm z-50 flex items-center justify-center p-4" + }, [ + React3.createElement("div", { + key: "modal", + className: "card-minimal rounded-xl p-6 max-w-lg w-full max-h-[90vh] overflow-y-auto custom-scrollbar" + }, [ + React3.createElement("div", { + key: "header", + className: "flex items-center justify-between mb-6" + }, [ + React3.createElement("h2", { + key: "title", + className: "text-xl font-semibold text-primary" + }, step === "select" ? "Select session type" : step === "details" ? "Security Features Details" : "Session payment"), + React3.createElement("button", { + key: "close", + onClick: onClose, + className: "text-gray-400 hover:text-white transition-colors" + }, React3.createElement("i", { className: "fas fa-times" })) + ]), + step === "select" && window.SessionTypeSelector && React3.createElement(window.SessionTypeSelector, { + key: "selector", + onSelectType: handleSelectType, + onCancel: onClose, + sessionManager + }), + step === "payment" && React3.createElement("div", { + key: "payment-step", + className: "space-y-6" + }, [ + React3.createElement("div", { + key: "session-info", + className: "text-center p-4 bg-orange-500/10 border border-orange-500/20 rounded-lg" + }, [ + React3.createElement("h3", { + key: "session-title", + className: "text-lg font-semibold text-orange-400 mb-2" + }, [ + `${selectedType.charAt(0).toUpperCase() + selectedType.slice(1)} session`, + invoice?.securityLevel && React3.createElement("span", { + key: "security-badge", + className: `text-xs px-2 py-1 rounded-full border ${getSecurityBadgeColor(invoice.securityLevel)}` + }, invoice.securityLevel.toUpperCase()) + ]), + React3.createElement("div", { + key: "session-details", + className: "text-sm text-secondary" + }, [ + React3.createElement("div", { key: "amount" }, `${pricing[selectedType].sats} sat for ${pricing[selectedType].hours}h`), + pricing[selectedType].usd > 0 && React3.createElement("div", { + key: "usd", + className: "text-gray-400" + }, `\u2248 ${pricing[selectedType].usd} USD`), + React3.createElement("button", { + key: "details-btn", + onClick: () => setStep("details"), + className: "mt-2 text-xs text-blue-400 hover:text-blue-300 underline cursor-pointer" + }, "\u{1F4CB} View Security Details") + ]) + ]), + timeLeft > 0 && paymentStatus === "created" && React3.createElement("div", { + key: "timer", + className: "text-center p-3 bg-yellow-500/10 border border-yellow-500/20 rounded" + }, [ + React3.createElement("div", { + key: "timer-text", + className: "text-yellow-400 font-medium" + }, `\u23F1\uFE0F Time to pay: ${formatTime(timeLeft)}`) + ]), + paymentStatus === "demo" && React3.createElement("div", { + key: "demo-payment", + className: "space-y-4" + }, [ + React3.createElement("div", { + key: "demo-info", + className: "p-4 bg-green-500/10 border border-green-500/20 rounded text-green-300 text-sm text-center" + }, [ + React3.createElement("div", { key: "demo-title", className: "font-medium mb-1" }, "\u{1F3AE} Demo Session Available"), + React3.createElement( + "div", + { key: "demo-details", className: "text-xs" }, + `Limited to ${invoice?.durationMinutes || 6} minutes for testing` + ) + ]), + invoice?.warning && React3.createElement("div", { + key: "demo-warning", + className: "p-3 bg-yellow-500/10 border border-yellow-500/20 rounded text-yellow-300 text-xs text-center" + }, invoice.warning), + React3.createElement("div", { + key: "demo-preimage", + className: "p-3 bg-gray-800/50 rounded border border-gray-600 text-xs font-mono text-gray-300" + }, [ + React3.createElement("div", { key: "preimage-label", className: "text-gray-400 mb-1" }, "Demo Preimage:"), + React3.createElement( + "div", + { key: "preimage-value", className: "break-all" }, + invoice?.preimage || "Generating..." + ) + ]), + React3.createElement("button", { + key: "demo-btn", + onClick: handleDemoSession, + disabled: isProcessing, + className: "w-full bg-green-600 hover:bg-green-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50 disabled:cursor-not-allowed" + }, [ + React3.createElement("i", { + key: "demo-icon", + className: `fas ${isProcessing ? "fa-spinner fa-spin" : "fa-play"} mr-2` + }), + isProcessing ? "Activating..." : "Activate Demo Session" + ]) + ]), + paymentStatus === "creating" && React3.createElement("div", { + key: "creating", + className: "text-center p-4" + }, [ + React3.createElement("i", { className: "fas fa-spinner fa-spin text-orange-400 text-2xl mb-2" }), + React3.createElement("div", { className: "text-primary" }, "Creating Lightning invoice..."), + React3.createElement("div", { className: "text-secondary text-sm mt-1" }, "Connecting to the Lightning Network...") + ]), + (paymentStatus === "created" || paymentStatus === "paying") && invoice && React3.createElement("div", { + key: "payment-methods", + className: "space-y-6" + }, [ + qrCodeUrl && React3.createElement("div", { + key: "qr-section", + className: "text-center" + }, [ + React3.createElement("div", { + key: "qr-container", + className: "bg-white p-4 rounded-lg inline-block" + }, [ + React3.createElement("img", { + key: "qr-img", + src: qrCodeUrl, + alt: "Lightning Payment QR Code", + className: "w-48 h-48" + }) + ]), + React3.createElement("div", { + key: "qr-hint", + className: "text-xs text-gray-400 mt-2" + }, "Scan with any Lightning wallet") + ]), + invoice.paymentRequest && React3.createElement("div", { + key: "payment-request", + className: "space-y-2" + }, [ + React3.createElement("div", { + key: "pr-label", + className: "text-sm font-medium text-primary" + }, "Lightning Payment Request:"), + React3.createElement("div", { + key: "pr-container", + className: "p-3 bg-gray-800/50 rounded border border-gray-600 text-xs font-mono text-gray-300 cursor-pointer hover:bg-gray-700/50 transition-colors", + onClick: () => copyToClipboard(invoice.paymentRequest), + title: "Click to copy" + }, [ + invoice.paymentRequest.substring(0, 60) + "...", + React3.createElement("i", { key: "copy-icon", className: "fas fa-copy ml-2 text-orange-400" }) + ]) + ]), + // WebLN Payment + React3.createElement("div", { + key: "webln-section", + className: "space-y-3" + }, [ + React3.createElement("h4", { + key: "webln-title", + className: "text-primary font-medium flex items-center" + }, [ + React3.createElement("i", { key: "bolt-icon", className: "fas fa-bolt text-orange-400 mr-2" }), + "WebLN wallet (recommended)" + ]), + React3.createElement("div", { + key: "webln-info", + className: "text-xs text-gray-400 mb-2" + }, "Alby, Zeus, or other WebLN-compatible wallets"), + React3.createElement("button", { + key: "webln-btn", + onClick: handleWebLNPayment, + disabled: isProcessing || paymentStatus === "paying", + className: "w-full bg-orange-600 hover:bg-orange-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50 disabled:cursor-not-allowed transition-colors" + }, [ + React3.createElement("i", { + key: "webln-icon", + className: `fas ${isProcessing ? "fa-spinner fa-spin" : "fa-bolt"} mr-2` + }), + paymentStatus === "paying" ? "Processing payment..." : "Pay via WebLN" + ]) + ]), + // Divider + React3.createElement("div", { + key: "divider", + className: "text-center text-gray-400 text-sm" + }, "\u2014 or \u2014"), + // Manual Verification + React3.createElement("div", { + key: "manual-section", + className: "space-y-3" + }, [ + React3.createElement("h4", { + key: "manual-title", + className: "text-primary font-medium" + }, "Manual payment confirmation"), + React3.createElement("div", { + key: "manual-info", + className: "text-xs text-gray-400" + }, "Pay the invoice in any wallet and enter the preimage.:"), + React3.createElement("input", { + key: "preimage-input", + type: "text", + value: preimageInput, + onChange: (e) => setPreimageInput(e.target.value), + placeholder: "Enter the preimage (64 hex characters)...", + className: "w-full p-3 bg-gray-800 border border-gray-600 rounded text-white placeholder-gray-400 text-sm font-mono", + maxLength: 64 + }), + React3.createElement("button", { + key: "verify-btn", + onClick: handleManualVerification, + disabled: isProcessing || !preimageInput.trim(), + className: "w-full bg-green-600 hover:bg-green-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50 disabled:cursor-not-allowed transition-colors" + }, [ + React3.createElement("i", { + key: "verify-icon", + className: `fas ${isProcessing ? "fa-spinner fa-spin" : "fa-check"} mr-2` + }), + isProcessing ? "Checking payment..." : "Confirm payment" + ]) + ]) + ]), + // Success State + paymentStatus === "paid" && React3.createElement("div", { + key: "success", + className: "text-center p-6 bg-green-500/10 border border-green-500/20 rounded-lg" + }, [ + React3.createElement("i", { key: "success-icon", className: "fas fa-check-circle text-green-400 text-3xl mb-3" }), + React3.createElement("div", { key: "success-title", className: "text-green-300 font-semibold text-lg mb-1" }, "\u2705 Payment confirmed!"), + React3.createElement("div", { key: "success-text", className: "text-green-400 text-sm" }, "The session will be activated upon connecting to the chat.") + ]), + // Error State + error && React3.createElement("div", { + key: "error", + className: "p-4 bg-red-500/10 border border-red-500/20 rounded-lg" + }, [ + React3.createElement("div", { + key: "error-content", + className: "flex items-start space-x-3" + }, [ + React3.createElement("i", { key: "error-icon", className: "fas fa-exclamation-triangle text-red-400 mt-0.5" }), + React3.createElement("div", { key: "error-text", className: "flex-1" }, [ + React3.createElement("div", { key: "error-message", className: "text-red-400 text-sm" }, error), + (error.includes("invoice") || paymentStatus === "failed") && React3.createElement("button", { + key: "retry-btn", + onClick: () => createRealInvoice(selectedType), + className: "mt-2 text-orange-400 hover:text-orange-300 underline text-sm" + }, "Create a new invoice") + ]) + ]) + ]), + paymentStatus !== "paid" && React3.createElement("div", { + key: "back-section", + className: "pt-4 border-t border-gray-600" + }, [ + React3.createElement("button", { + key: "back-btn", + onClick: () => setStep("select"), + className: "w-full bg-gray-600 hover:bg-gray-500 text-white py-2 px-4 rounded transition-colors" + }, [ + React3.createElement("i", { key: "back-icon", className: "fas fa-arrow-left mr-2" }), + "Choose another session" + ]) + ]) + ]), + // Security Details Step + step === "details" && React3.createElement("div", { + key: "details-step", + className: "space-y-6" + }, [ + React3.createElement("div", { + key: "details-header", + className: "text-center p-4 bg-blue-500/10 border border-blue-500/20 rounded-lg" + }, [ + React3.createElement("h3", { + key: "details-title", + className: "text-lg font-semibold text-blue-400 mb-2" + }, getSecurityFeaturesInfo(selectedType).title), + React3.createElement("p", { + key: "details-description", + className: "text-sm text-blue-300" + }, getSecurityFeaturesInfo(selectedType).description) + ]), + // Available Features + React3.createElement("div", { key: "available-features" }, [ + React3.createElement("h4", { + key: "available-title", + className: "text-sm font-medium text-green-300 mb-3 flex items-center" + }, [ + React3.createElement("i", { + key: "check-icon", + className: "fas fa-check-circle mr-2" + }), + "Available Security Features" + ]), + React3.createElement("div", { + key: "available-list", + className: "grid grid-cols-1 gap-2" + }, getSecurityFeaturesInfo(selectedType).available.map( + (feature, index) => React3.createElement("div", { + key: index, + className: "flex items-center gap-2 text-sm text-green-300" + }, [ + React3.createElement("i", { + key: "check", + className: "fas fa-check text-green-400 w-4" + }), + React3.createElement("span", { + key: "text" + }, feature) + ]) + )) + ]), + // Unavailable Features (if any) + getSecurityFeaturesInfo(selectedType).unavailable.length > 0 && React3.createElement("div", { key: "unavailable-features" }, [ + React3.createElement("h4", { + key: "unavailable-title", + className: "text-sm font-medium text-red-300 mb-3 flex items-center" + }, [ + React3.createElement("i", { + key: "minus-icon", + className: "fas fa-minus-circle mr-2" + }), + "Not Available in This Session" + ]), + React3.createElement("div", { + key: "unavailable-list", + className: "grid grid-cols-1 gap-2" + }, getSecurityFeaturesInfo(selectedType).unavailable.map( + (feature, index) => React3.createElement("div", { + key: index, + className: "flex items-center gap-2 text-sm text-red-300" + }, [ + React3.createElement("i", { + key: "minus", + className: "fas fa-minus text-red-400 w-4" + }), + React3.createElement("span", { + key: "text" + }, feature) + ]) + )) + ]), + // Upgrade Information + React3.createElement("div", { key: "upgrade-info" }, [ + React3.createElement("h4", { + key: "upgrade-title", + className: "text-sm font-medium text-blue-300 mb-3 flex items-center" + }, [ + React3.createElement("i", { + key: "upgrade-icon", + className: "fas fa-arrow-up mr-2" + }), + "Upgrade for More Security" + ]), + React3.createElement("div", { + key: "upgrade-content", + className: "p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg" + }, [ + React3.createElement("div", { + key: "upgrade-next", + className: "text-sm font-medium text-blue-300 mb-2" + }, getSecurityFeaturesInfo(selectedType).upgrade.next), + React3.createElement("div", { + key: "upgrade-features", + className: "grid grid-cols-1 gap-1" + }, getSecurityFeaturesInfo(selectedType).upgrade.features.map( + (feature, index) => React3.createElement("div", { + key: index, + className: "flex items-center gap-2 text-xs text-blue-300" + }, [ + React3.createElement("i", { + key: "arrow", + className: "fas fa-arrow-right text-blue-400 w-3" + }), + React3.createElement("span", { + key: "text" + }, feature) + ]) + )) + ]) + ]), + // Back Button + React3.createElement("div", { + key: "details-back-section", + className: "pt-4 border-t border-gray-600" + }, [ + React3.createElement("button", { + key: "details-back-btn", + onClick: () => setStep("payment"), + className: "w-full bg-gray-600 hover:bg-gray-500 text-white py-2 px-4 rounded transition-colors" + }, [ + React3.createElement("i", { key: "back-icon", className: "fas fa-arrow-left mr-2" }), + "Back to Payment" + ]) + ]) + ]) + ]) + ]); +}; +window.PaymentModal = PaymentModal; + +// src/components/ui/DownloadApps.jsx +var DownloadApps = () => { + const apps = [ + { id: "web", name: "Web App", subtitle: "Browser Version", icon: "fas fa-globe", platform: "Web", isActive: true, url: "https://securebitchat.github.io/securebit-chat/", color: "green" }, + { id: "windows", name: "Windows", subtitle: "Desktop App", icon: "fab fa-windows", platform: "Desktop", isActive: false, url: "#", color: "blue" }, + { id: "macos", name: "macOS", subtitle: "Desktop App", icon: "fab fa-apple", platform: "Desktop", isActive: false, url: "#", color: "gray" }, + { id: "linux", name: "Linux", subtitle: "Desktop App", icon: "fab fa-linux", platform: "Desktop", isActive: false, url: "#", color: "orange" }, + { id: "ios", name: "iOS", subtitle: "iPhone & iPad", icon: "fab fa-apple", platform: "Mobile", isActive: false, url: "https://apps.apple.com/app/securebit-chat/", color: "blue" }, + { id: "android", name: "Android", subtitle: "Google Play", icon: "fab fa-android", platform: "Mobile", isActive: false, url: "https://play.google.com/store/apps/details?id=com.securebit.chat", color: "green" } + ]; + const handleDownload = (app) => { + if (app.isActive) window.open(app.url, "_blank"); + }; + const desktopApps = apps.filter((a) => a.platform !== "Mobile"); + const mobileApps = apps.filter((a) => a.platform === "Mobile"); + const cardSize = "w-28 h-28"; + return React.createElement("div", { className: "mt-20 px-6" }, [ + // Header + React.createElement("div", { key: "header", className: "text-center max-w-3xl mx-auto mb-12" }, [ + React.createElement("h3", { key: "title", className: "text-3xl font-bold text-primary mb-3" }, "Download SecureBit.chat"), + React.createElement("p", { key: "subtitle", className: "text-secondary text-lg mb-5" }, "Stay secure on every device. Choose your platform and start chatting privately.") + ]), + React.createElement( + "div", + { key: "desktop-row", className: "hidden sm:flex justify-center flex-wrap gap-6 mb-6" }, + desktopApps.map( + (app) => React.createElement("div", { + key: app.id, + className: `group relative ${cardSize} rounded-2xl overflow-hidden card-minimal cursor-pointer` + }, [ + React.createElement("i", { + key: "bg-icon", + className: `${app.icon} absolute text-[3rem] text-white/10 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none transition-all duration-500 group-hover:scale-105` + }), + React.createElement("div", { + key: "overlay", + className: "absolute inset-0 bg-black/30 backdrop-blur-md flex flex-col items-center justify-center text-center opacity-0 transition-opacity duration-300 group-hover:opacity-100" + }, [ + React.createElement("h4", { key: "name", className: `text-sm font-semibold text-primary mb-1` }, app.name), + React.createElement("p", { key: "subtitle", className: `text-xs text-secondary mb-2` }, app.subtitle), + app.isActive ? React.createElement("button", { + key: "btn", + onClick: () => handleDownload(app), + className: `px-2 py-1 rounded-xl bg-emerald-500 text-black font-medium hover:bg-emerald-600 transition-colors text-xs` + }, app.id === "web" ? "Launch" : "Download") : React.createElement("span", { key: "coming", className: "text-gray-400 font-medium text-xs" }, "Coming Soon") + ]) + ]) + ) + ), + React.createElement( + "div", + { key: "mobile-row", className: "flex justify-center gap-6" }, + mobileApps.map( + (app) => React.createElement("div", { + key: app.id, + className: `group relative ${cardSize} rounded-2xl overflow-hidden card-minimal cursor-pointer` + }, [ + React.createElement("i", { + key: "bg-icon", + className: `${app.icon} absolute text-[3rem] text-white/10 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none transition-all duration-500 group-hover:scale-105` + }), + React.createElement("div", { + key: "overlay", + className: "absolute inset-0 bg-black/30 backdrop-blur-md flex flex-col items-center justify-center text-center opacity-0 transition-opacity duration-300 group-hover:opacity-100" + }, [ + React.createElement("h4", { key: "name", className: `text-sm font-semibold text-primary mb-1` }, app.name), + React.createElement("p", { key: "subtitle", className: `text-xs text-secondary mb-2` }, app.subtitle), + app.isActive ? React.createElement("button", { + key: "btn", + onClick: () => handleDownload(app), + className: `px-2 py-1 rounded-xl bg-emerald-500 text-black font-medium hover:bg-emerald-600 transition-colors text-xs` + }, "Download") : React.createElement("span", { key: "coming", className: "text-gray-400 font-medium text-xs" }, "Coming Soon") + ]) + ]) + ) + ) + ]); +}; +window.DownloadApps = DownloadApps; + +// src/components/ui/FileTransfer.jsx +var FileTransferComponent = ({ webrtcManager, isConnected }) => { + const [dragOver, setDragOver] = React.useState(false); + const [transfers, setTransfers] = React.useState({ sending: [], receiving: [] }); + const [readyFiles, setReadyFiles] = React.useState([]); + const fileInputRef = React.useRef(null); + React.useEffect(() => { + if (!isConnected || !webrtcManager) return; + const updateTransfers = () => { + const currentTransfers = webrtcManager.getFileTransfers(); + setTransfers(currentTransfers); + }; + const interval = setInterval(updateTransfers, 500); + return () => clearInterval(interval); + }, [isConnected, webrtcManager]); + React.useEffect(() => { + if (!webrtcManager) return; + webrtcManager.setFileTransferCallbacks( + // Progress callback - ТОЛЬКО обновляем UI, НЕ отправляем в чат + (progress) => { + const currentTransfers = webrtcManager.getFileTransfers(); + setTransfers(currentTransfers); + }, + // File received callback - добавляем кнопку скачивания в UI + (fileData) => { + setReadyFiles((prev) => { + if (prev.some((f) => f.fileId === fileData.fileId)) return prev; + return [...prev, { + fileId: fileData.fileId, + fileName: fileData.fileName, + fileSize: fileData.fileSize, + mimeType: fileData.mimeType, + getBlob: fileData.getBlob, + getObjectURL: fileData.getObjectURL, + revokeObjectURL: fileData.revokeObjectURL + }]; + }); + const currentTransfers = webrtcManager.getFileTransfers(); + setTransfers(currentTransfers); + }, + // Error callback + (error) => { + const currentTransfers = webrtcManager.getFileTransfers(); + setTransfers(currentTransfers); + } + ); + }, [webrtcManager]); + const handleFileSelect = async (files) => { + if (!isConnected || !webrtcManager) { + alert("\u0421\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E. \u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435."); + return; + } + if (!webrtcManager.isConnected() || !webrtcManager.isVerified) { + alert("\u0421\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u043D\u0435 \u0433\u043E\u0442\u043E\u0432\u043E \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043B\u043E\u0432. \u0414\u043E\u0436\u0434\u0438\u0442\u0435\u0441\u044C \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u044F."); + return; + } + for (const file of files) { + try { + const validation = webrtcManager.validateFile(file); + if (!validation.isValid) { + const errorMessage = validation.errors.join(". "); + alert(`\u0424\u0430\u0439\u043B ${file.name} \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D: ${errorMessage}`); + continue; + } + await webrtcManager.sendFile(file); + } catch (error) { + if (error.message.includes("Connection not ready")) { + alert(`\u0424\u0430\u0439\u043B ${file.name} \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D \u0441\u0435\u0439\u0447\u0430\u0441. \u041F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u0438 \u043F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u0441\u043D\u043E\u0432\u0430.`); + } else if (error.message.includes("File too large") || error.message.includes("exceeds maximum")) { + alert(`\u0424\u0430\u0439\u043B ${file.name} \u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0431\u043E\u043B\u044C\u0448\u043E\u0439: ${error.message}`); + } else if (error.message.includes("Maximum concurrent transfers")) { + alert(`\u0414\u043E\u0441\u0442\u0438\u0433\u043D\u0443\u0442 \u043B\u0438\u043C\u0438\u0442 \u043E\u0434\u043D\u043E\u0432\u0440\u0435\u043C\u0435\u043D\u043D\u044B\u0445 \u043F\u0435\u0440\u0435\u0434\u0430\u0447. \u0414\u043E\u0436\u0434\u0438\u0442\u0435\u0441\u044C \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u0442\u0435\u043A\u0443\u0449\u0438\u0445 \u043F\u0435\u0440\u0435\u0434\u0430\u0447.`); + } else if (error.message.includes("File type not allowed")) { + alert(`\u0422\u0438\u043F \u0444\u0430\u0439\u043B\u0430 ${file.name} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F: ${error.message}`); + } else { + alert(`\u041E\u0448\u0438\u0431\u043A\u0430 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438 \u0444\u0430\u0439\u043B\u0430 ${file.name}: ${error.message}`); + } + } + } + }; + const handleDrop = (e) => { + e.preventDefault(); + setDragOver(false); + const files = Array.from(e.dataTransfer.files); + handleFileSelect(files); + }; + const handleDragOver = (e) => { + e.preventDefault(); + setDragOver(true); + }; + const handleDragLeave = (e) => { + e.preventDefault(); + setDragOver(false); + }; + const handleFileInputChange = (e) => { + const files = Array.from(e.target.files); + handleFileSelect(files); + e.target.value = ""; + }; + const formatFileSize = (bytes) => { + if (bytes === 0) return "0 B"; + const k = 1024; + const sizes = ["B", "KB", "MB", "GB"]; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; + }; + const getStatusIcon = (status) => { + switch (status) { + case "metadata_sent": + case "preparing": + return "fas fa-cog fa-spin"; + case "transmitting": + case "receiving": + return "fas fa-exchange-alt fa-pulse"; + case "assembling": + return "fas fa-puzzle-piece fa-pulse"; + case "completed": + return "fas fa-check text-green-400"; + case "failed": + return "fas fa-times text-red-400"; + default: + return "fas fa-circle"; + } + }; + const getStatusText = (status) => { + switch (status) { + case "metadata_sent": + return "\u041F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0430..."; + case "transmitting": + return "\u041E\u0442\u043F\u0440\u0430\u0432\u043A\u0430..."; + case "receiving": + return "\u041F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u0435..."; + case "assembling": + return "\u0421\u0431\u043E\u0440\u043A\u0430 \u0444\u0430\u0439\u043B\u0430..."; + case "completed": + return "\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E"; + case "failed": + return "\u041E\u0448\u0438\u0431\u043A\u0430"; + default: + return status; + } + }; + if (!isConnected) { + return React.createElement("div", { + className: "p-4 text-center text-muted" + }, "\u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u043E\u0432 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0430 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0440\u0438 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u043E\u043C \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0438"); + } + const isConnectionReady = webrtcManager && webrtcManager.isConnected() && webrtcManager.isVerified; + if (!isConnectionReady) { + return React.createElement("div", { + className: "p-4 text-center text-yellow-600" + }, [ + React.createElement("i", { + key: "icon", + className: "fas fa-exclamation-triangle mr-2" + }), + "\u0421\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u0443\u0441\u0442\u0430\u043D\u0430\u0432\u043B\u0438\u0432\u0430\u0435\u0442\u0441\u044F... \u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u043E\u0432 \u0431\u0443\u0434\u0435\u0442 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0430 \u043F\u043E\u0441\u043B\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438." + ]); + } + return React.createElement("div", { + className: "file-transfer-component" + }, [ + // File Drop Zone + React.createElement("div", { + key: "drop-zone", + className: `file-drop-zone ${dragOver ? "drag-over" : ""}`, + onDrop: handleDrop, + onDragOver: handleDragOver, + onDragLeave: handleDragLeave, + onClick: () => fileInputRef.current?.click() + }, [ + React.createElement("div", { + key: "drop-content", + className: "drop-content" + }, [ + React.createElement("i", { + key: "icon", + className: "fas fa-cloud-upload-alt text-2xl mb-2 text-blue-400" + }), + React.createElement("p", { + key: "text", + className: "text-primary font-medium" + }, "Drag files here or click to select"), + React.createElement("p", { + key: "subtext", + className: "text-muted text-sm" + }, "Maximum size: 100 MB per file") + ]) + ]), + // Hidden file input + React.createElement("input", { + key: "file-input", + ref: fileInputRef, + type: "file", + multiple: true, + className: "hidden", + onChange: handleFileInputChange + }), + // Active Transfers + (transfers.sending.length > 0 || transfers.receiving.length > 0) && React.createElement("div", { + key: "transfers", + className: "active-transfers mt-4" + }, [ + React.createElement("h4", { + key: "title", + className: "text-primary font-medium mb-3 flex items-center" + }, [ + React.createElement("i", { + key: "icon", + className: "fas fa-exchange-alt mr-2" + }), + "\u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u043E\u0432" + ]), + // Sending files + ...transfers.sending.map( + (transfer) => React.createElement("div", { + key: `send-${transfer.fileId}`, + className: "transfer-item bg-blue-500/10 border border-blue-500/20 rounded-lg p-3 mb-2" + }, [ + React.createElement("div", { + key: "header", + className: "flex items-center justify-between mb-2" + }, [ + React.createElement("div", { + key: "info", + className: "flex items-center" + }, [ + React.createElement("i", { + key: "icon", + className: "fas fa-upload text-blue-400 mr-2" + }), + React.createElement("span", { + key: "name", + className: "text-primary font-medium text-sm" + }, transfer.fileName), + React.createElement("span", { + key: "size", + className: "text-muted text-xs ml-2" + }, formatFileSize(transfer.fileSize)) + ]), + React.createElement("button", { + key: "cancel", + onClick: () => webrtcManager.cancelFileTransfer(transfer.fileId), + className: "text-red-400 hover:text-red-300 text-xs" + }, [ + React.createElement("i", { + className: "fas fa-times" + }) + ]) + ]), + React.createElement("div", { + key: "progress", + className: "progress-bar" + }, [ + React.createElement("div", { + key: "fill", + className: "progress-fill bg-blue-400", + style: { width: `${transfer.progress}%` } + }), + React.createElement("div", { + key: "text", + className: "progress-text text-xs flex items-center justify-between" + }, [ + React.createElement("span", { + key: "status", + className: "flex items-center" + }, [ + React.createElement("i", { + key: "icon", + className: `${getStatusIcon(transfer.status)} mr-1` + }), + getStatusText(transfer.status) + ]), + React.createElement("span", { + key: "percent" + }, `${transfer.progress.toFixed(1)}%`) + ]) + ]) + ]) + ), + // Receiving files + ...transfers.receiving.map( + (transfer) => React.createElement("div", { + key: `recv-${transfer.fileId}`, + className: "transfer-item bg-green-500/10 border border-green-500/20 rounded-lg p-3 mb-2" + }, [ + React.createElement("div", { + key: "header", + className: "flex items-center justify-between mb-2" + }, [ + React.createElement("div", { + key: "info", + className: "flex items-center" + }, [ + React.createElement("i", { + key: "icon", + className: "fas fa-download text-green-400 mr-2" + }), + React.createElement("span", { + key: "name", + className: "text-primary font-medium text-sm" + }, transfer.fileName), + React.createElement("span", { + key: "size", + className: "text-muted text-xs ml-2" + }, formatFileSize(transfer.fileSize)) + ]), + React.createElement("div", { key: "actions", className: "flex items-center space-x-2" }, [ + (() => { + const rf = readyFiles.find((f) => f.fileId === transfer.fileId); + if (!rf || transfer.status !== "completed") return null; + return React.createElement("button", { + key: "download", + className: "text-green-400 hover:text-green-300 text-xs flex items-center", + onClick: async () => { + try { + const url = await rf.getObjectURL(); + const a = document.createElement("a"); + a.href = url; + a.download = rf.fileName || "file"; + a.click(); + rf.revokeObjectURL(url); + } catch (e) { + alert("Failed to start download: " + e.message); + } + } + }, [ + React.createElement("i", { key: "i", className: "fas fa-download mr-1" }), + "Download" + ]); + })(), + React.createElement("button", { + key: "cancel", + onClick: () => webrtcManager.cancelFileTransfer(transfer.fileId), + className: "text-red-400 hover:text-red-300 text-xs" + }, [ + React.createElement("i", { + className: "fas fa-times" + }) + ]) + ]) + ]), + React.createElement("div", { + key: "progress", + className: "progress-bar" + }, [ + React.createElement("div", { + key: "fill", + className: "progress-fill bg-green-400", + style: { width: `${transfer.progress}%` } + }), + React.createElement("div", { + key: "text", + className: "progress-text text-xs flex items-center justify-between" + }, [ + React.createElement("span", { + key: "status", + className: "flex items-center" + }, [ + React.createElement("i", { + key: "icon", + className: `${getStatusIcon(transfer.status)} mr-1` + }), + getStatusText(transfer.status) + ]), + React.createElement("span", { + key: "percent" + }, `${transfer.progress.toFixed(1)}%`) + ]) + ]) + ]) + ) + ]) + ]); +}; +window.FileTransferComponent = FileTransferComponent; + +// src/scripts/app-boot.js +window.EnhancedSecureCryptoUtils = EnhancedSecureCryptoUtils; +window.EnhancedSecureWebRTCManager = EnhancedSecureWebRTCManager; +window.PayPerSessionManager = PayPerSessionManager; +window.EnhancedSecureFileTransfer = EnhancedSecureFileTransfer; +var start = () => { + if (typeof window.initializeApp === "function") { + window.initializeApp(); + } else if (window.DEBUG_MODE) { + console.error("initializeApp is not defined on window"); + } +}; +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", start); +} else { + start(); +} +//# sourceMappingURL=app-boot.js.map diff --git a/dist/app-boot.js.map b/dist/app-boot.js.map new file mode 100644 index 0000000..5871ae8 --- /dev/null +++ b/dist/app-boot.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../src/crypto/EnhancedSecureCryptoUtils.js", "../src/transfer/EnhancedSecureFileTransfer.js", "../src/network/EnhancedSecureWebRTCManager.js", "../src/session/PayPerSessionManager.js", "../src/components/ui/SessionTimer.jsx", "../src/components/ui/Header.jsx", "../src/components/ui/SessionTypeSelector.jsx", "../src/components/ui/LightningPayment.jsx", "../src/components/ui/PaymentModal.jsx", "../src/components/ui/DownloadApps.jsx", "../src/components/ui/FileTransfer.jsx", "../src/scripts/app-boot.js"], + "sourcesContent": ["class EnhancedSecureCryptoUtils {\n\n static _keyMetadata = new WeakMap();\n \n // Initialize secure logging system after class definition\n\n // Utility to sort object keys for deterministic serialization\n static sortObjectKeys(obj) {\n if (typeof obj !== 'object' || obj === null) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(EnhancedSecureCryptoUtils.sortObjectKeys);\n }\n\n const sortedObj = {};\n Object.keys(obj).sort().forEach(key => {\n sortedObj[key] = EnhancedSecureCryptoUtils.sortObjectKeys(obj[key]);\n });\n return sortedObj;\n }\n\n // Utility to assert CryptoKey type and properties\n static assertCryptoKey(key, expectedName = null, expectedUsages = []) {\n if (!(key instanceof CryptoKey)) throw new Error('Expected CryptoKey');\n if (expectedName && key.algorithm?.name !== expectedName) {\n throw new Error(`Expected algorithm ${expectedName}, got ${key.algorithm?.name}`);\n }\n for (const u of expectedUsages) {\n if (!key.usages || !key.usages.includes(u)) {\n throw new Error(`Missing required key usage: ${u}`);\n }\n }\n }\n // Helper function to convert ArrayBuffer to Base64\n static arrayBufferToBase64(buffer) {\n let binary = '';\n const bytes = new Uint8Array(buffer);\n const len = bytes.byteLength;\n for (let i = 0; i < len; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n\n // Helper function to convert Base64 to ArrayBuffer\n static base64ToArrayBuffer(base64) {\n try {\n // Validate input\n if (typeof base64 !== 'string' || !base64) {\n throw new Error('Invalid base64 input: must be a non-empty string');\n }\n\n // Remove any whitespace and validate base64 format\n const cleanBase64 = base64.trim();\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(cleanBase64)) {\n throw new Error('Invalid base64 format');\n }\n\n // Handle empty string case\n if (cleanBase64 === '') {\n return new ArrayBuffer(0);\n }\n\n const binaryString = atob(cleanBase64);\n const len = binaryString.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n } catch (error) {\n console.error('Base64 to ArrayBuffer conversion failed:', error.message);\n throw new Error(`Base64 conversion error: ${error.message}`);\n }\n }\n\n // Helper function to convert hex string to Uint8Array\n static hexToUint8Array(hexString) {\n try {\n if (!hexString || typeof hexString !== 'string') {\n throw new Error('Invalid hex string input: must be a non-empty string');\n }\n\n // Remove colons and spaces from hex string (e.g., \"aa:bb:cc\" -> \"aabbcc\")\n const cleanHex = hexString.replace(/:/g, '').replace(/\\s/g, '');\n \n // Validate hex format\n if (!/^[0-9a-fA-F]*$/.test(cleanHex)) {\n throw new Error('Invalid hex format: contains non-hex characters');\n }\n \n // Ensure even length\n if (cleanHex.length % 2 !== 0) {\n throw new Error('Invalid hex format: odd length');\n }\n\n // Convert hex string to bytes\n const bytes = new Uint8Array(cleanHex.length / 2);\n for (let i = 0; i < cleanHex.length; i += 2) {\n bytes[i / 2] = parseInt(cleanHex.substr(i, 2), 16);\n }\n \n return bytes;\n } catch (error) {\n console.error('Hex to Uint8Array conversion failed:', error.message);\n throw new Error(`Hex conversion error: ${error.message}`);\n }\n }\n\n static async encryptData(data, password) {\n try {\n const dataString = typeof data === 'string' ? data : JSON.stringify(data);\n const salt = crypto.getRandomValues(new Uint8Array(16));\n const encoder = new TextEncoder();\n const passwordBuffer = encoder.encode(password);\n\n const keyMaterial = await crypto.subtle.importKey(\n 'raw',\n passwordBuffer,\n { name: 'PBKDF2' },\n false,\n ['deriveKey']\n );\n\n const key = await crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt,\n iterations: 100000,\n hash: 'SHA-256',\n },\n keyMaterial,\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt']\n );\n\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const dataBuffer = encoder.encode(dataString);\n const encrypted = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: iv },\n key,\n dataBuffer\n );\n\n const encryptedPackage = {\n version: '1.0',\n salt: Array.from(salt),\n iv: Array.from(iv),\n data: Array.from(new Uint8Array(encrypted)),\n timestamp: Date.now(),\n };\n\n const packageString = JSON.stringify(encryptedPackage);\n return EnhancedSecureCryptoUtils.arrayBufferToBase64(new TextEncoder().encode(packageString).buffer);\n\n } catch (error) {\n console.error('Encryption failed:', error.message);\n throw new Error(`Encryption error: ${error.message}`);\n }\n }\n\n static async decryptData(encryptedData, password) {\n try {\n const packageBuffer = EnhancedSecureCryptoUtils.base64ToArrayBuffer(encryptedData);\n const packageString = new TextDecoder().decode(packageBuffer);\n const encryptedPackage = JSON.parse(packageString);\n\n if (!encryptedPackage.version || !encryptedPackage.salt || !encryptedPackage.iv || !encryptedPackage.data) {\n throw new Error('Invalid encrypted data format');\n }\n\n const salt = new Uint8Array(encryptedPackage.salt);\n const iv = new Uint8Array(encryptedPackage.iv);\n const encrypted = new Uint8Array(encryptedPackage.data);\n\n const encoder = new TextEncoder();\n const passwordBuffer = encoder.encode(password);\n\n const keyMaterial = await crypto.subtle.importKey(\n 'raw',\n passwordBuffer,\n { name: 'PBKDF2' },\n false,\n ['deriveKey']\n );\n\n const key = await crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt,\n iterations: 100000,\n hash: 'SHA-256'\n },\n keyMaterial,\n { name: 'AES-GCM', length: 256 },\n false,\n ['decrypt']\n );\n\n const decrypted = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv },\n key,\n encrypted\n );\n\n const decryptedString = new TextDecoder().decode(decrypted);\n\n try {\n return JSON.parse(decryptedString);\n } catch {\n return decryptedString;\n }\n\n } catch (error) {\n console.error('Decryption failed:', error.message);\n throw new Error(`Decryption error: ${error.message}`);\n }\n }\n\n \n // Generate secure password for data exchange\n static generateSecurePassword() {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?';\n const length = 32; \n const randomValues = new Uint32Array(length);\n crypto.getRandomValues(randomValues);\n \n let password = '';\n for (let i = 0; i < length; i++) {\n password += chars[randomValues[i] % chars.length];\n }\n return password;\n }\n\n // Real security level calculation with actual verification\n static async calculateSecurityLevel(securityManager) {\n let score = 0;\n const maxScore = 100; // Fixed: Changed from 110 to 100 for cleaner percentage\n const verificationResults = {};\n \n try {\n // Fallback to basic calculation if securityManager is not fully initialized\n if (!securityManager || !securityManager.securityFeatures) {\n console.warn('Security manager not fully initialized, using fallback calculation');\n return {\n level: 'INITIALIZING',\n score: 0,\n color: 'gray',\n verificationResults: {},\n timestamp: Date.now(),\n details: 'Security system initializing...',\n isRealData: false\n };\n }\n\n // Check session type to determine available features\n const sessionType = securityManager.currentSessionType || 'demo';\n const isDemoSession = sessionType === 'demo';\n \n // 1. Base encryption verification (20 points) - Available in demo\n try {\n if (await EnhancedSecureCryptoUtils.verifyEncryption(securityManager)) {\n score += 20;\n verificationResults.encryption = { passed: true, details: 'AES-GCM encryption verified', points: 20 };\n } else {\n verificationResults.encryption = { passed: false, details: 'Encryption not working', points: 0 };\n }\n } catch (error) {\n verificationResults.encryption = { passed: false, details: `Encryption check failed: ${error.message}`, points: 0 };\n }\n \n // 2. Simple key exchange verification (15 points) - Available in demo\n try {\n if (await EnhancedSecureCryptoUtils.verifyECDHKeyExchange(securityManager)) {\n score += 15;\n verificationResults.keyExchange = { passed: true, details: 'Simple key exchange verified', points: 15 };\n } else {\n verificationResults.keyExchange = { passed: false, details: 'Key exchange failed', points: 0 };\n }\n } catch (error) {\n verificationResults.keyExchange = { passed: false, details: `Key exchange check failed: ${error.message}`, points: 0 };\n }\n \n // 3. Message integrity verification (10 points) - Available in demo\n if (await EnhancedSecureCryptoUtils.verifyMessageIntegrity(securityManager)) {\n score += 10;\n verificationResults.messageIntegrity = { passed: true, details: 'Message integrity verified', points: 10 };\n } else {\n verificationResults.messageIntegrity = { passed: false, details: 'Message integrity failed', points: 0 };\n }\n \n // 4. Rate limiting verification (5 points) - Available in demo\n if (await EnhancedSecureCryptoUtils.verifyRateLimiting(securityManager)) {\n score += 5;\n verificationResults.rateLimiting = { passed: true, details: 'Rate limiting active', points: 5 };\n } else {\n verificationResults.rateLimiting = { passed: false, details: 'Rate limiting not working', points: 0 };\n }\n \n // 5. ECDSA signatures verification (15 points) - Only for enhanced sessions\n if (!isDemoSession && await EnhancedSecureCryptoUtils.verifyECDSASignatures(securityManager)) {\n score += 15;\n verificationResults.ecdsa = { passed: true, details: 'ECDSA signatures verified', points: 15 };\n } else {\n const reason = isDemoSession ? 'Enhanced session required - feature not available' : 'ECDSA signatures failed';\n verificationResults.ecdsa = { passed: false, details: reason, points: 0 };\n }\n \n // 6. Metadata protection verification (10 points) - Only for enhanced sessions\n if (!isDemoSession && await EnhancedSecureCryptoUtils.verifyMetadataProtection(securityManager)) {\n score += 10;\n verificationResults.metadataProtection = { passed: true, details: 'Metadata protection verified', points: 10 };\n } else {\n const reason = isDemoSession ? 'Enhanced session required - feature not available' : 'Metadata protection failed';\n verificationResults.metadataProtection = { passed: false, details: reason, points: 0 };\n }\n \n // 7. Perfect Forward Secrecy verification (10 points) - Only for enhanced sessions\n if (!isDemoSession && await EnhancedSecureCryptoUtils.verifyPFS(securityManager)) {\n score += 10;\n verificationResults.pfs = { passed: true, details: 'Perfect Forward Secrecy active', points: 10 };\n } else {\n const reason = isDemoSession ? 'Enhanced session required - feature not available' : 'PFS not active';\n verificationResults.pfs = { passed: false, details: reason, points: 0 };\n }\n \n // 8. Nested encryption verification (5 points) - Only for enhanced sessions\n if (!isDemoSession && await EnhancedSecureCryptoUtils.verifyNestedEncryption(securityManager)) {\n score += 5;\n verificationResults.nestedEncryption = { passed: true, details: 'Nested encryption active', points: 5 };\n } else {\n const reason = isDemoSession ? 'Enhanced session required - feature not available' : 'Nested encryption failed';\n verificationResults.nestedEncryption = { passed: false, details: reason, points: 0 };\n }\n \n // 9. Packet padding verification (5 points) - Only for enhanced sessions\n if (!isDemoSession && await EnhancedSecureCryptoUtils.verifyPacketPadding(securityManager)) {\n score += 5;\n verificationResults.packetPadding = { passed: true, details: 'Packet padding active', points: 5 };\n } else {\n const reason = isDemoSession ? 'Enhanced session required - feature not available' : 'Packet padding failed';\n verificationResults.packetPadding = { passed: false, details: reason, points: 0 };\n }\n \n // 10. Advanced features verification (10 points) - Only for premium sessions\n if (sessionType === 'premium' && await EnhancedSecureCryptoUtils.verifyAdvancedFeatures(securityManager)) {\n score += 10;\n verificationResults.advancedFeatures = { passed: true, details: 'Advanced features active', points: 10 };\n } else {\n const reason = sessionType === 'demo' ? 'Premium session required - feature not available' : \n sessionType === 'basic' ? 'Premium session required - feature not available' : 'Advanced features failed';\n verificationResults.advancedFeatures = { passed: false, details: reason, points: 0 };\n }\n \n const percentage = Math.round((score / maxScore) * 100);\n \n // Calculate available checks based on session type\n const availableChecks = isDemoSession ? 4 : 10; // Demo: encryption(20) + key exchange(15) + message integrity(10) + rate limiting(5) = 50 points\n const passedChecks = Object.values(verificationResults).filter(r => r.passed).length;\n \n const result = {\n level: percentage >= 85 ? 'HIGH' : percentage >= 65 ? 'MEDIUM' : percentage >= 35 ? 'LOW' : 'CRITICAL',\n score: percentage,\n color: percentage >= 85 ? 'green' : percentage >= 65 ? 'orange' : percentage >= 35 ? 'yellow' : 'red',\n verificationResults,\n timestamp: Date.now(),\n details: `Real verification: ${score}/${maxScore} security checks passed (${passedChecks}/${availableChecks} available)`,\n isRealData: true,\n passedChecks: passedChecks,\n totalChecks: availableChecks,\n sessionType: sessionType,\n maxPossibleScore: isDemoSession ? 50 : 100 // Demo sessions can only get max 50 points (4 checks)\n };\n \n console.log('Real security level calculated:', {\n score: percentage,\n level: result.level,\n passedChecks: passedChecks,\n totalChecks: availableChecks,\n sessionType: sessionType,\n maxPossibleScore: result.maxPossibleScore\n });\n \n return result;\n } catch (error) {\n console.error('Security level calculation failed:', error.message);\n return {\n level: 'UNKNOWN',\n score: 0,\n color: 'red',\n verificationResults: {},\n timestamp: Date.now(),\n details: `Verification failed: ${error.message}`,\n isRealData: false\n };\n }\n }\n\n // Real verification functions\n static async verifyEncryption(securityManager) {\n try {\n if (!securityManager.encryptionKey) return false;\n \n // Test actual encryption/decryption\n const testData = 'Test encryption verification';\n const encoder = new TextEncoder();\n const testBuffer = encoder.encode(testData);\n const iv = crypto.getRandomValues(new Uint8Array(12));\n \n const encrypted = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n securityManager.encryptionKey,\n testBuffer\n );\n \n const decrypted = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv },\n securityManager.encryptionKey,\n encrypted\n );\n \n const decryptedText = new TextDecoder().decode(decrypted);\n return decryptedText === testData;\n } catch (error) {\n console.error('Encryption verification failed:', error.message);\n return false;\n }\n }\n \n static async verifyECDHKeyExchange(securityManager) {\n try {\n if (!securityManager.ecdhKeyPair || !securityManager.ecdhKeyPair.privateKey || !securityManager.ecdhKeyPair.publicKey) {\n return false;\n }\n \n // Test that keys are actually ECDH keys\n const keyType = securityManager.ecdhKeyPair.privateKey.algorithm.name;\n const curve = securityManager.ecdhKeyPair.privateKey.algorithm.namedCurve;\n \n return keyType === 'ECDH' && (curve === 'P-384' || curve === 'P-256');\n } catch (error) {\n console.error('ECDH verification failed:', error.message);\n return false;\n }\n }\n \n static async verifyECDSASignatures(securityManager) {\n try {\n if (!securityManager.ecdsaKeyPair || !securityManager.ecdsaKeyPair.privateKey || !securityManager.ecdsaKeyPair.publicKey) {\n return false;\n }\n \n // Test actual signing and verification\n const testData = 'Test ECDSA signature verification';\n const encoder = new TextEncoder();\n const testBuffer = encoder.encode(testData);\n \n const signature = await crypto.subtle.sign(\n { name: 'ECDSA', hash: 'SHA-256' },\n securityManager.ecdsaKeyPair.privateKey,\n testBuffer\n );\n \n const isValid = await crypto.subtle.verify(\n { name: 'ECDSA', hash: 'SHA-256' },\n securityManager.ecdsaKeyPair.publicKey,\n signature,\n testBuffer\n );\n \n return isValid;\n } catch (error) {\n console.error('ECDSA verification failed:', error.message);\n return false;\n }\n }\n \n static async verifyMessageIntegrity(securityManager) {\n try {\n // Check if macKey exists and is a valid CryptoKey\n if (!securityManager.macKey || !(securityManager.macKey instanceof CryptoKey)) {\n console.warn('MAC key not available or invalid for message integrity verification');\n return false;\n }\n \n // Test message integrity with HMAC\n const testData = 'Test message integrity verification';\n const encoder = new TextEncoder();\n const testBuffer = encoder.encode(testData);\n \n const hmac = await crypto.subtle.sign(\n { name: 'HMAC', hash: 'SHA-256' },\n securityManager.macKey,\n testBuffer\n );\n \n const isValid = await crypto.subtle.verify(\n { name: 'HMAC', hash: 'SHA-256' },\n securityManager.macKey,\n hmac,\n testBuffer\n );\n \n return isValid;\n } catch (error) {\n console.error('Message integrity verification failed:', error.message);\n return false;\n }\n }\n \n static async verifyNestedEncryption(securityManager) {\n try {\n // Check if nestedEncryptionKey exists and is a valid CryptoKey\n if (!securityManager.nestedEncryptionKey || !(securityManager.nestedEncryptionKey instanceof CryptoKey)) {\n console.warn('Nested encryption key not available or invalid');\n return false;\n }\n \n // Test nested encryption\n const testData = 'Test nested encryption verification';\n const encoder = new TextEncoder();\n const testBuffer = encoder.encode(testData);\n \n // Simulate nested encryption\n const encrypted = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: crypto.getRandomValues(new Uint8Array(12)) },\n securityManager.nestedEncryptionKey,\n testBuffer\n );\n \n return encrypted && encrypted.byteLength > 0;\n } catch (error) {\n console.error('Nested encryption verification failed:', error.message);\n return false;\n }\n }\n \n static async verifyPacketPadding(securityManager) {\n try {\n if (!securityManager.paddingConfig || !securityManager.paddingConfig.enabled) return false;\n \n // Test packet padding functionality\n const testData = 'Test packet padding verification';\n const encoder = new TextEncoder();\n const testBuffer = encoder.encode(testData);\n \n // Simulate packet padding\n const paddingSize = Math.floor(Math.random() * (securityManager.paddingConfig.maxPadding - securityManager.paddingConfig.minPadding)) + securityManager.paddingConfig.minPadding;\n const paddedData = new Uint8Array(testBuffer.byteLength + paddingSize);\n paddedData.set(new Uint8Array(testBuffer), 0);\n \n return paddedData.byteLength >= testBuffer.byteLength + securityManager.paddingConfig.minPadding;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Packet padding verification failed', { error: error.message });\n return false;\n }\n }\n \n static async verifyAdvancedFeatures(securityManager) {\n try {\n // Test advanced features like traffic obfuscation, fake traffic, etc.\n const hasFakeTraffic = securityManager.fakeTrafficConfig && securityManager.fakeTrafficConfig.enabled;\n const hasDecoyChannels = securityManager.decoyChannelsConfig && securityManager.decoyChannelsConfig.enabled;\n const hasAntiFingerprinting = securityManager.antiFingerprintingConfig && securityManager.antiFingerprintingConfig.enabled;\n \n return hasFakeTraffic || hasDecoyChannels || hasAntiFingerprinting;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Advanced features verification failed', { error: error.message });\n return false;\n }\n }\n \n static async verifyMutualAuth(securityManager) {\n try {\n if (!securityManager.isVerified || !securityManager.verificationCode) return false;\n \n // Test mutual authentication\n return securityManager.isVerified && securityManager.verificationCode.length > 0;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Mutual auth verification failed', { error: error.message });\n return false;\n }\n }\n \n static async verifyMetadataProtection(securityManager) {\n try {\n if (!securityManager.metadataKey) return false;\n \n // Test metadata protection\n const testData = 'Test metadata protection verification';\n const encoder = new TextEncoder();\n const testBuffer = encoder.encode(testData);\n \n const encrypted = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: crypto.getRandomValues(new Uint8Array(12)) },\n securityManager.metadataKey,\n testBuffer\n );\n \n return encrypted && encrypted.byteLength > 0;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Metadata protection verification failed', { error: error.message });\n return false;\n }\n }\n \n static async verifyReplayProtection(securityManager) {\n try {\n if (!securityManager.processedMessageIds || !securityManager.sequenceNumber) return false;\n \n // Test replay protection\n const testId = Date.now().toString();\n if (securityManager.processedMessageIds.has(testId)) return false;\n \n securityManager.processedMessageIds.add(testId);\n return true;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Replay protection verification failed', { error: error.message });\n return false;\n }\n }\n \n static async verifyNonExtractableKeys(securityManager) {\n try {\n if (!securityManager.encryptionKey) return false;\n \n // Test if keys are non-extractable\n const keyData = await crypto.subtle.exportKey('raw', securityManager.encryptionKey);\n return keyData && keyData.byteLength > 0;\n } catch (error) {\n // If export fails, keys are non-extractable (which is good)\n return true;\n }\n }\n \n static async verifyEnhancedValidation(securityManager) {\n try {\n if (!securityManager.securityFeatures) return false;\n \n // Test enhanced validation features\n const hasValidation = securityManager.securityFeatures.hasEnhancedValidation || \n securityManager.securityFeatures.hasEnhancedReplayProtection;\n \n return hasValidation;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Enhanced validation verification failed', { error: error.message });\n return false;\n }\n }\n \n static async verifyRateLimiting(securityManager) {\n try {\n const testId = 'test_' + Date.now();\n const canProceed = await EnhancedSecureCryptoUtils.rateLimiter.checkMessageRate(testId, 1, 60000);\n \n return securityManager.rateLimiterId && \n EnhancedSecureCryptoUtils.rateLimiter &&\n typeof EnhancedSecureCryptoUtils.rateLimiter.checkMessageRate === 'function' &&\n canProceed === true;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Rate limiting verification failed', { error: error.message });\n return false;\n }\n }\n \n static async verifyPFS(securityManager) {\n try {\n // Check if PFS is active\n return securityManager.securityFeatures &&\n securityManager.securityFeatures.hasPFS === true &&\n securityManager.keyRotationInterval &&\n securityManager.currentKeyVersion !== undefined &&\n securityManager.keyVersions &&\n securityManager.keyVersions instanceof Map;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'PFS verification failed', { error: error.message });\n return false;\n }\n }\n\n // Rate limiting implementation\n static rateLimiter = {\n messages: new Map(),\n connections: new Map(),\n locks: new Map(),\n \n async checkMessageRate(identifier, limit = 60, windowMs = 60000) {\n if (typeof identifier !== 'string' || identifier.length > 256) {\n return false;\n }\n \n const key = `msg_${identifier}`;\n\n if (this.locks.has(key)) {\n\n await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 10) + 5));\n return this.checkMessageRate(identifier, limit, windowMs);\n }\n \n this.locks.set(key, true);\n \n try {\n const now = Date.now();\n \n if (!this.messages.has(key)) {\n this.messages.set(key, []);\n }\n \n const timestamps = this.messages.get(key);\n \n const validTimestamps = timestamps.filter(ts => now - ts < windowMs);\n \n if (validTimestamps.length >= limit) {\n return false; \n }\n \n validTimestamps.push(now);\n this.messages.set(key, validTimestamps);\n return true;\n } finally {\n this.locks.delete(key);\n }\n },\n \n async checkConnectionRate(identifier, limit = 5, windowMs = 300000) {\n if (typeof identifier !== 'string' || identifier.length > 256) {\n return false;\n }\n \n const key = `conn_${identifier}`;\n \n if (this.locks.has(key)) {\n await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 10) + 5));\n return this.checkConnectionRate(identifier, limit, windowMs);\n }\n \n this.locks.set(key, true);\n \n try {\n const now = Date.now();\n \n if (!this.connections.has(key)) {\n this.connections.set(key, []);\n }\n \n const timestamps = this.connections.get(key);\n const validTimestamps = timestamps.filter(ts => now - ts < windowMs);\n \n if (validTimestamps.length >= limit) {\n return false;\n }\n \n validTimestamps.push(now);\n this.connections.set(key, validTimestamps);\n return true;\n } finally {\n this.locks.delete(key);\n }\n },\n \n cleanup() {\n const now = Date.now();\n const maxAge = 3600000; \n \n for (const [key, timestamps] of this.messages.entries()) {\n if (this.locks.has(key)) continue;\n \n const valid = timestamps.filter(ts => now - ts < maxAge);\n if (valid.length === 0) {\n this.messages.delete(key);\n } else {\n this.messages.set(key, valid);\n }\n }\n \n for (const [key, timestamps] of this.connections.entries()) {\n if (this.locks.has(key)) continue;\n \n const valid = timestamps.filter(ts => now - ts < maxAge);\n if (valid.length === 0) {\n this.connections.delete(key);\n } else {\n this.connections.set(key, valid);\n }\n }\n\n for (const lockKey of this.locks.keys()) {\n const keyTimestamp = parseInt(lockKey.split('_').pop()) || 0;\n if (now - keyTimestamp > 30000) {\n this.locks.delete(lockKey);\n }\n }\n }\n};\n\n static validateSalt(salt) {\n if (!salt || salt.length !== 64) {\n throw new Error('Salt must be exactly 64 bytes');\n }\n \n const uniqueBytes = new Set(salt);\n if (uniqueBytes.size < 16) {\n throw new Error('Salt has insufficient entropy');\n }\n \n return true;\n }\n\n // Secure logging without data leaks\n static secureLog = {\n logs: [],\n maxLogs: 100,\n isProductionMode: false,\n \n // Initialize production mode detection\n init() {\n this.isProductionMode = this._detectProductionMode();\n if (this.isProductionMode) {\n console.log('[SecureChat] Production mode detected - sensitive logging disabled');\n }\n },\n \n _detectProductionMode() {\n return (\n (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') ||\n (!window.DEBUG_MODE && !window.DEVELOPMENT_MODE) ||\n (window.location.hostname && !window.location.hostname.includes('localhost') && \n !window.location.hostname.includes('127.0.0.1') && \n !window.location.hostname.includes('.local')) ||\n (typeof window.webpackHotUpdate === 'undefined' && !window.location.search.includes('debug'))\n );\n },\n \n log(level, message, context = {}) {\n const sanitizedContext = this.sanitizeContext(context);\n const logEntry = {\n timestamp: Date.now(),\n level,\n message,\n context: sanitizedContext,\n id: crypto.getRandomValues(new Uint32Array(1))[0]\n };\n \n this.logs.push(logEntry);\n \n // Keep only recent logs\n if (this.logs.length > this.maxLogs) {\n this.logs = this.logs.slice(-this.maxLogs);\n }\n \n // Production-safe console output\n if (this.isProductionMode) {\n if (level === 'error') {\n // \u0412 production \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u0442\u043E\u043B\u044C\u043A\u043E \u043A\u043E\u0434 \u043E\u0448\u0438\u0431\u043A\u0438 \u0431\u0435\u0437 \u0434\u0435\u0442\u0430\u043B\u0435\u0439\n console.error(`\u274C [SecureChat] ${message} [ERROR_CODE: ${this._generateErrorCode(message)}]`);\n } else if (level === 'warn') {\n // \u0412 production \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0435 \u0431\u0435\u0437 \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442\u0430\n console.warn(`\u26A0\uFE0F [SecureChat] ${message}`);\n } else {\n // \u0412 production \u043D\u0435 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C info/debug \u043B\u043E\u0433\u0438\n return;\n }\n } else {\n // Development mode - \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u0432\u0441\u0435\n if (level === 'error') {\n console.error(`\u274C [SecureChat] ${message}`, { errorType: sanitizedContext?.constructor?.name || 'Unknown' });\n } else if (level === 'warn') {\n console.warn(`\u26A0\uFE0F [SecureChat] ${message}`, { details: sanitizedContext });\n } else {\n console.log(`[SecureChat] ${message}`, sanitizedContext);\n }\n }\n },\n \n // \u0413\u0435\u043D\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u044B\u0439 \u043A\u043E\u0434 \u043E\u0448\u0438\u0431\u043A\u0438 \u0434\u043B\u044F production\n _generateErrorCode(message) {\n const hash = message.split('').reduce((a, b) => {\n a = ((a << 5) - a) + b.charCodeAt(0);\n return a & a;\n }, 0);\n return Math.abs(hash).toString(36).substring(0, 6).toUpperCase();\n },\n \n sanitizeContext(context) {\n if (!context || typeof context !== 'object') {\n return context;\n }\n \n const sensitivePatterns = [\n /key/i, /secret/i, /password/i, /token/i, /signature/i,\n /challenge/i, /proof/i, /salt/i, /iv/i, /nonce/i, /hash/i,\n /fingerprint/i, /mac/i, /private/i, /encryption/i, /decryption/i\n ];\n \n const sanitized = {};\n for (const [key, value] of Object.entries(context)) {\n const isSensitive = sensitivePatterns.some(pattern => \n pattern.test(key) || (typeof value === 'string' && pattern.test(value))\n );\n \n if (isSensitive) {\n sanitized[key] = '[REDACTED]';\n } else if (typeof value === 'string' && value.length > 100) {\n sanitized[key] = value.substring(0, 100) + '...[TRUNCATED]';\n } else if (value instanceof ArrayBuffer || value instanceof Uint8Array) {\n sanitized[key] = `[${value.constructor.name}(${value.byteLength || value.length} bytes)]`;\n } else if (value && typeof value === 'object' && !Array.isArray(value)) {\n // \u0420\u0435\u043A\u0443\u0440\u0441\u0438\u0432\u043D\u0430\u044F \u0441\u0430\u043D\u0438\u0442\u0438\u0437\u0430\u0446\u0438\u044F \u0434\u043B\u044F \u043E\u0431\u044A\u0435\u043A\u0442\u043E\u0432\n sanitized[key] = this.sanitizeContext(value);\n } else {\n sanitized[key] = value;\n }\n }\n return sanitized;\n },\n \n getLogs(level = null) {\n if (level) {\n return this.logs.filter(log => log.level === level);\n }\n return [...this.logs];\n },\n \n clearLogs() {\n this.logs = [];\n },\n \n // \u041C\u0435\u0442\u043E\u0434 \u0434\u043B\u044F \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438 \u043E\u0448\u0438\u0431\u043E\u043A \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0432 production\n async sendErrorToServer(errorCode, message, context = {}) {\n if (!this.isProductionMode) {\n return; // \u0412 development \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u043C\n }\n \n try {\n // \u041E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u043C \u0442\u043E\u043B\u044C\u043A\u043E \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u0443\u044E \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044E\n const safeErrorData = {\n errorCode,\n timestamp: Date.now(),\n userAgent: navigator.userAgent.substring(0, 100),\n url: window.location.href.substring(0, 100)\n };\n \n // \u0417\u0434\u0435\u0441\u044C \u043C\u043E\u0436\u043D\u043E \u0434\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0443 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\n // await fetch('/api/error-log', { method: 'POST', body: JSON.stringify(safeErrorData) });\n \n if (window.DEBUG_MODE) {\n console.log('[SecureChat] Error logged to server:', safeErrorData);\n }\n } catch (e) {\n // \u041D\u0435 \u043B\u043E\u0433\u0438\u0440\u0443\u0435\u043C \u043E\u0448\u0438\u0431\u043A\u0438 \u043B\u043E\u0433\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F\n }\n }\n };\n\n // Generate ECDH key pair for secure key exchange (non-extractable) with fallback\n static async generateECDHKeyPair() {\n try {\n // Try P-384 first\n try {\n const keyPair = await crypto.subtle.generateKey(\n {\n name: 'ECDH',\n namedCurve: 'P-384'\n },\n false, // Non-extractable for enhanced security\n ['deriveKey']\n );\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'ECDH key pair generated successfully (P-384)', {\n curve: 'P-384',\n extractable: false\n });\n \n return keyPair;\n } catch (p384Error) {\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'P-384 generation failed, trying P-256', { error: p384Error.message });\n \n // Fallback to P-256\n const keyPair = await crypto.subtle.generateKey(\n {\n name: 'ECDH',\n namedCurve: 'P-256'\n },\n false, // Non-extractable for enhanced security\n ['deriveKey']\n );\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'ECDH key pair generated successfully (P-256 fallback)', {\n curve: 'P-256',\n extractable: false\n });\n \n return keyPair;\n }\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'ECDH key generation failed', { error: error.message });\n throw new Error('Failed to create keys for secure exchange');\n }\n }\n\n // Generate ECDSA key pair for digital signatures with fallback\n static async generateECDSAKeyPair() {\n try {\n // Try P-384 first\n try {\n const keyPair = await crypto.subtle.generateKey(\n {\n name: 'ECDSA',\n namedCurve: 'P-384'\n },\n false, // Non-extractable for enhanced security\n ['sign', 'verify']\n );\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'ECDSA key pair generated successfully (P-384)', {\n curve: 'P-384',\n extractable: false\n });\n \n return keyPair;\n } catch (p384Error) {\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'P-384 generation failed, trying P-256', { error: p384Error.message });\n \n // Fallback to P-256\n const keyPair = await crypto.subtle.generateKey(\n {\n name: 'ECDSA',\n namedCurve: 'P-256'\n },\n false, // Non-extractable for enhanced security\n ['sign', 'verify']\n );\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'ECDSA key pair generated successfully (P-256 fallback)', {\n curve: 'P-256',\n extractable: false\n });\n \n return keyPair;\n }\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'ECDSA key generation failed', { error: error.message });\n throw new Error('Failed to generate keys for digital signatures');\n }\n }\n\n // Sign data with ECDSA (P-384 or P-256)\n static async signData(privateKey, data) {\n try {\n const encoder = new TextEncoder();\n const dataBuffer = typeof data === 'string' ? encoder.encode(data) : data;\n \n // Try SHA-384 first, fallback to SHA-256\n try {\n const signature = await crypto.subtle.sign(\n {\n name: 'ECDSA',\n hash: 'SHA-384'\n },\n privateKey,\n dataBuffer\n );\n \n return Array.from(new Uint8Array(signature));\n } catch (sha384Error) {\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'SHA-384 signing failed, trying SHA-256', { error: sha384Error.message });\n \n const signature = await crypto.subtle.sign(\n {\n name: 'ECDSA',\n hash: 'SHA-256'\n },\n privateKey,\n dataBuffer\n );\n \n return Array.from(new Uint8Array(signature));\n }\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Data signing failed', { error: error.message });\n throw new Error('Failed to sign data');\n }\n }\n\n // Verify ECDSA signature (P-384 or P-256)\n static async verifySignature(publicKey, signature, data) {\n try {\n const encoder = new TextEncoder();\n const dataBuffer = typeof data === 'string' ? encoder.encode(data) : data;\n const signatureBuffer = new Uint8Array(signature);\n \n // Try SHA-384 first, fallback to SHA-256\n try {\n const isValid = await crypto.subtle.verify(\n {\n name: 'ECDSA',\n hash: 'SHA-384'\n },\n publicKey,\n signatureBuffer,\n dataBuffer\n );\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'Signature verification completed (SHA-384)', {\n isValid,\n dataSize: dataBuffer.length\n });\n \n return isValid;\n } catch (sha384Error) {\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'SHA-384 verification failed, trying SHA-256', { error: sha384Error.message });\n \n const isValid = await crypto.subtle.verify(\n {\n name: 'ECDSA',\n hash: 'SHA-256'\n },\n publicKey,\n signatureBuffer,\n dataBuffer\n );\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'Signature verification completed (SHA-256 fallback)', {\n isValid,\n dataSize: dataBuffer.length\n });\n \n return isValid;\n }\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Signature verification failed', { error: error.message });\n throw new Error('Failed to verify digital signature');\n }\n }\n\n // Enhanced DER/SPKI validation with full ASN.1 parsing\n static async validateKeyStructure(keyData, expectedAlgorithm = 'ECDH') {\n try {\n if (!Array.isArray(keyData) || keyData.length === 0) {\n throw new Error('Invalid key data format');\n }\n\n const keyBytes = new Uint8Array(keyData);\n\n // Size limits to prevent DoS\n if (keyBytes.length < 50) {\n throw new Error('Key data too short - invalid SPKI structure');\n }\n if (keyBytes.length > 2000) {\n throw new Error('Key data too long - possible attack');\n }\n\n // Parse ASN.1 DER structure\n const asn1 = EnhancedSecureCryptoUtils.parseASN1(keyBytes);\n \n // Validate SPKI structure\n if (!asn1 || asn1.tag !== 0x30) {\n throw new Error('Invalid SPKI structure - missing SEQUENCE tag');\n }\n\n // SPKI should have exactly 2 elements: AlgorithmIdentifier and BIT STRING\n if (asn1.children.length !== 2) {\n throw new Error(`Invalid SPKI structure - expected 2 elements, got ${asn1.children.length}`);\n }\n\n // Validate AlgorithmIdentifier\n const algIdentifier = asn1.children[0];\n if (algIdentifier.tag !== 0x30) {\n throw new Error('Invalid AlgorithmIdentifier - not a SEQUENCE');\n }\n\n // Parse algorithm OID\n const algOid = algIdentifier.children[0];\n if (algOid.tag !== 0x06) {\n throw new Error('Invalid algorithm OID - not an OBJECT IDENTIFIER');\n }\n\n // Validate algorithm OID based on expected algorithm\n const oidBytes = algOid.value;\n const oidString = EnhancedSecureCryptoUtils.oidToString(oidBytes);\n \n // Check for expected algorithms\n const validAlgorithms = {\n 'ECDH': ['1.2.840.10045.2.1'], // id-ecPublicKey\n 'ECDSA': ['1.2.840.10045.2.1'], // id-ecPublicKey (same as ECDH)\n 'RSA': ['1.2.840.113549.1.1.1'], // rsaEncryption\n 'AES-GCM': ['2.16.840.1.101.3.4.1.6', '2.16.840.1.101.3.4.1.46'] // AES-128-GCM, AES-256-GCM\n };\n\n const expectedOids = validAlgorithms[expectedAlgorithm];\n if (!expectedOids) {\n throw new Error(`Unknown algorithm: ${expectedAlgorithm}`);\n }\n\n if (!expectedOids.includes(oidString)) {\n throw new Error(`Invalid algorithm OID: expected ${expectedOids.join(' or ')}, got ${oidString}`);\n }\n\n // For EC algorithms, validate curve parameters\n if (expectedAlgorithm === 'ECDH' || expectedAlgorithm === 'ECDSA') {\n if (algIdentifier.children.length < 2) {\n throw new Error('Missing curve parameters for EC key');\n }\n\n const curveOid = algIdentifier.children[1];\n if (curveOid.tag !== 0x06) {\n throw new Error('Invalid curve OID - not an OBJECT IDENTIFIER');\n }\n\n const curveOidString = EnhancedSecureCryptoUtils.oidToString(curveOid.value);\n \n // Only allow P-256 and P-384 curves\n const validCurves = {\n '1.2.840.10045.3.1.7': 'P-256', // secp256r1\n '1.3.132.0.34': 'P-384' // secp384r1\n };\n\n if (!validCurves[curveOidString]) {\n throw new Error(`Invalid or unsupported curve OID: ${curveOidString}`);\n }\n\n EnhancedSecureCryptoUtils.secureLog.log('info', 'EC key curve validated', {\n curve: validCurves[curveOidString],\n oid: curveOidString\n });\n }\n\n // Validate public key BIT STRING\n const publicKeyBitString = asn1.children[1];\n if (publicKeyBitString.tag !== 0x03) {\n throw new Error('Invalid public key - not a BIT STRING');\n }\n\n // Check for unused bits (should be 0 for public keys)\n if (publicKeyBitString.value[0] !== 0x00) {\n throw new Error(`Invalid BIT STRING - unexpected unused bits: ${publicKeyBitString.value[0]}`);\n }\n\n // For EC keys, validate point format\n if (expectedAlgorithm === 'ECDH' || expectedAlgorithm === 'ECDSA') {\n const pointData = publicKeyBitString.value.slice(1); // Skip unused bits byte\n \n // Check for uncompressed point format (0x04)\n if (pointData[0] !== 0x04) {\n throw new Error(`Invalid EC point format: expected uncompressed (0x04), got 0x${pointData[0].toString(16)}`);\n }\n\n // Validate point size based on curve\n const expectedSizes = {\n 'P-256': 65, // 1 + 32 + 32\n 'P-384': 97 // 1 + 48 + 48\n };\n\n // We already validated the curve above, so we can determine expected size\n const curveOidString = EnhancedSecureCryptoUtils.oidToString(algIdentifier.children[1].value);\n const curveName = curveOidString === '1.2.840.10045.3.1.7' ? 'P-256' : 'P-384';\n const expectedSize = expectedSizes[curveName];\n\n if (pointData.length !== expectedSize) {\n throw new Error(`Invalid EC point size for ${curveName}: expected ${expectedSize}, got ${pointData.length}`);\n }\n }\n\n // Additional validation: try to import the key\n try {\n const algorithm = expectedAlgorithm === 'ECDSA' || expectedAlgorithm === 'ECDH'\n ? { name: expectedAlgorithm, namedCurve: 'P-384' }\n : { name: expectedAlgorithm };\n\n const usages = expectedAlgorithm === 'ECDSA' ? ['verify'] : [];\n \n await crypto.subtle.importKey('spki', keyBytes.buffer, algorithm, false, usages);\n } catch (importError) {\n // Try P-256 as fallback for EC keys\n if (expectedAlgorithm === 'ECDSA' || expectedAlgorithm === 'ECDH') {\n try {\n const algorithm = { name: expectedAlgorithm, namedCurve: 'P-256' };\n const usages = expectedAlgorithm === 'ECDSA' ? ['verify'] : [];\n await crypto.subtle.importKey('spki', keyBytes.buffer, algorithm, false, usages);\n } catch (fallbackError) {\n throw new Error(`Key import validation failed: ${fallbackError.message}`);\n }\n } else {\n throw new Error(`Key import validation failed: ${importError.message}`);\n }\n }\n\n EnhancedSecureCryptoUtils.secureLog.log('info', 'Key structure validation passed', {\n keyLen: keyBytes.length,\n algorithm: expectedAlgorithm,\n asn1Valid: true,\n oidValid: true,\n importValid: true\n });\n\n return true;\n } catch (err) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Key structure validation failed', {\n error: err.message,\n algorithm: expectedAlgorithm\n });\n throw new Error(`Invalid key structure: ${err.message}`);\n }\n }\n\n // ASN.1 DER parser helper\n static parseASN1(bytes, offset = 0) {\n if (offset >= bytes.length) {\n return null;\n }\n\n const tag = bytes[offset];\n let lengthOffset = offset + 1;\n \n if (lengthOffset >= bytes.length) {\n throw new Error('Truncated ASN.1 structure');\n }\n\n let length = bytes[lengthOffset];\n let valueOffset = lengthOffset + 1;\n\n // Handle long form length\n if (length & 0x80) {\n const numLengthBytes = length & 0x7f;\n if (numLengthBytes > 4) {\n throw new Error('ASN.1 length too large');\n }\n \n length = 0;\n for (let i = 0; i < numLengthBytes; i++) {\n if (valueOffset + i >= bytes.length) {\n throw new Error('Truncated ASN.1 length');\n }\n length = (length << 8) | bytes[valueOffset + i];\n }\n valueOffset += numLengthBytes;\n }\n\n if (valueOffset + length > bytes.length) {\n throw new Error('ASN.1 structure extends beyond data');\n }\n\n const value = bytes.slice(valueOffset, valueOffset + length);\n const node = {\n tag: tag,\n length: length,\n value: value,\n children: []\n };\n\n // Parse children for SEQUENCE and SET\n if (tag === 0x30 || tag === 0x31) {\n let childOffset = 0;\n while (childOffset < value.length) {\n const child = EnhancedSecureCryptoUtils.parseASN1(value, childOffset);\n if (!child) break;\n node.children.push(child);\n childOffset = childOffset + 1 + child.lengthBytes + child.length;\n }\n }\n\n // Calculate how many bytes were used for length encoding\n node.lengthBytes = valueOffset - lengthOffset;\n \n return node;\n }\n\n // OID decoder helper\n static oidToString(bytes) {\n if (!bytes || bytes.length === 0) {\n throw new Error('Empty OID');\n }\n\n const parts = [];\n \n // First byte encodes first two components\n const first = Math.floor(bytes[0] / 40);\n const second = bytes[0] % 40;\n parts.push(first);\n parts.push(second);\n\n // Decode remaining components\n let value = 0;\n for (let i = 1; i < bytes.length; i++) {\n value = (value << 7) | (bytes[i] & 0x7f);\n if (!(bytes[i] & 0x80)) {\n parts.push(value);\n value = 0;\n }\n }\n\n return parts.join('.');\n }\n\n // Helper to validate and sanitize OID string\n static validateOidString(oidString) {\n // OID format: digits separated by dots\n const oidRegex = /^[0-9]+(\\.[0-9]+)*$/;\n if (!oidRegex.test(oidString)) {\n throw new Error(`Invalid OID format: ${oidString}`);\n }\n\n const parts = oidString.split('.').map(Number);\n \n // First component must be 0, 1, or 2\n if (parts[0] > 2) {\n throw new Error(`Invalid OID first component: ${parts[0]}`);\n }\n\n // If first component is 0 or 1, second must be <= 39\n if ((parts[0] === 0 || parts[0] === 1) && parts[1] > 39) {\n throw new Error(`Invalid OID second component: ${parts[1]} (must be <= 39 for first component ${parts[0]})`);\n }\n\n return true;\n }\n\n // Export public key for transmission with signature \n static async exportPublicKeyWithSignature(publicKey, signingKey, keyType = 'ECDH') {\n try {\n // Validate key type\n if (!['ECDH', 'ECDSA'].includes(keyType)) {\n throw new Error('Invalid key type');\n }\n \n const exported = await crypto.subtle.exportKey('spki', publicKey);\n const keyData = Array.from(new Uint8Array(exported));\n \n await EnhancedSecureCryptoUtils.validateKeyStructure(keyData, keyType);\n \n // Create signed key package\n const keyPackage = {\n keyType,\n keyData,\n timestamp: Date.now(),\n version: '4.0'\n };\n \n // Sign the key package\n const packageString = JSON.stringify(keyPackage);\n const signature = await EnhancedSecureCryptoUtils.signData(signingKey, packageString);\n \n const signedPackage = {\n ...keyPackage,\n signature\n };\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'Public key exported with signature', {\n keyType,\n keySize: keyData.length,\n signed: true\n });\n \n return signedPackage;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Public key export failed', {\n error: error.message,\n keyType\n });\n throw new Error(`Failed to export ${keyType} key: ${error.message}`);\n }\n }\n\n // Import and verify signed public key\n static async importSignedPublicKey(signedPackage, verifyingKey, expectedKeyType = 'ECDH') {\n try {\n // Validate package structure\n if (!signedPackage || typeof signedPackage !== 'object') {\n throw new Error('Invalid signed package format');\n }\n \n const { keyType, keyData, timestamp, version, signature } = signedPackage;\n \n if (!keyType || !keyData || !timestamp || !signature) {\n throw new Error('Missing required fields in signed package');\n }\n \n if (!EnhancedSecureCryptoUtils.constantTimeCompare(keyType, expectedKeyType)) {\n throw new Error(`Key type mismatch: expected ${expectedKeyType}, got ${keyType}`);\n }\n \n // Check timestamp (reject keys older than 1 hour)\n const keyAge = Date.now() - timestamp;\n if (keyAge > 3600000) {\n throw new Error('Signed key package is too old');\n }\n \n await EnhancedSecureCryptoUtils.validateKeyStructure(keyData, keyType);\n \n // Verify signature\n const packageCopy = { keyType, keyData, timestamp, version };\n const packageString = JSON.stringify(packageCopy);\n const isValidSignature = await EnhancedSecureCryptoUtils.verifySignature(verifyingKey, signature, packageString);\n \n if (!isValidSignature) {\n throw new Error('Invalid signature on key package - possible MITM attack');\n }\n \n // Import the key with fallback support\n const keyBytes = new Uint8Array(keyData);\n \n // Try P-384 first\n try {\n const algorithm = keyType === 'ECDH' ?\n { name: 'ECDH', namedCurve: 'P-384' }\n : { name: 'ECDSA', namedCurve: 'P-384' };\n \n const keyUsages = keyType === 'ECDH' ? [] : ['verify'];\n \n const publicKey = await crypto.subtle.importKey(\n 'spki',\n keyBytes,\n algorithm,\n false, // Non-extractable\n keyUsages\n );\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'Signed public key imported successfully (P-384)', {\n keyType,\n signatureValid: true,\n keyAge: Math.round(keyAge / 1000) + 's'\n });\n \n return publicKey;\n } catch (p384Error) {\n // Fallback to P-256\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'P-384 import failed, trying P-256', {\n error: p384Error.message\n });\n \n const algorithm = keyType === 'ECDH' ?\n { name: 'ECDH', namedCurve: 'P-256' }\n : { name: 'ECDSA', namedCurve: 'P-256' };\n \n const keyUsages = keyType === 'ECDH' ? [] : ['verify'];\n \n const publicKey = await crypto.subtle.importKey(\n 'spki',\n keyBytes,\n algorithm,\n false, // Non-extractable\n keyUsages\n );\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'Signed public key imported successfully (P-256 fallback)', {\n keyType,\n signatureValid: true,\n keyAge: Math.round(keyAge / 1000) + 's'\n });\n \n return publicKey;\n }\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Signed public key import failed', {\n error: error.message,\n expectedKeyType\n });\n throw new Error(`Failed to import the signed key: ${error.message}`);\n }\n }\n\n // Legacy export for backward compatibility\n static async exportPublicKey(publicKey) {\n try {\n const exported = await crypto.subtle.exportKey('spki', publicKey);\n const keyData = Array.from(new Uint8Array(exported));\n \n await EnhancedSecureCryptoUtils.validateKeyStructure(keyData, 'ECDH');\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'Legacy public key exported', { keySize: keyData.length });\n return keyData;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Legacy public key export failed', { error: error.message });\n throw new Error('Failed to export the public key');\n }\n }\n\n // Legacy import for backward compatibility with fallback\n static async importPublicKey(keyData) {\n try {\n await EnhancedSecureCryptoUtils.validateKeyStructure(keyData, 'ECDH');\n \n const keyBytes = new Uint8Array(keyData);\n \n // Try P-384 first\n try {\n const publicKey = await crypto.subtle.importKey(\n 'spki',\n keyBytes,\n {\n name: 'ECDH',\n namedCurve: 'P-384'\n },\n false, // Non-extractable\n []\n );\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'Legacy public key imported (P-384)', { keySize: keyData.length });\n return publicKey;\n } catch (p384Error) {\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'P-384 import failed, trying P-256', { error: p384Error.message });\n \n // Fallback to P-256\n const publicKey = await crypto.subtle.importKey(\n 'spki',\n keyBytes,\n {\n name: 'ECDH',\n namedCurve: 'P-256'\n },\n false, // Non-extractable\n []\n );\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'Legacy public key imported (P-256 fallback)', { keySize: keyData.length });\n return publicKey;\n }\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Legacy public key import failed', { error: error.message });\n throw new Error('Failed to import the public key');\n }\n }\n\n\n // Method to check if a key is trusted\n static isKeyTrusted(keyOrFingerprint) {\n if (keyOrFingerprint instanceof CryptoKey) {\n const meta = EnhancedSecureCryptoUtils._keyMetadata.get(keyOrFingerprint);\n return meta ? meta.trusted === true : false;\n } else if (keyOrFingerprint && keyOrFingerprint._securityMetadata) {\n // Check by key metadata\n return keyOrFingerprint._securityMetadata.trusted === true;\n }\n\n return false;\n }\n\n static async importPublicKeyFromSignedPackage(signedPackage, verifyingKey = null, options = {}) {\n try {\n if (!signedPackage || !signedPackage.keyData || !signedPackage.signature) {\n throw new Error('Invalid signed key package format');\n }\n\n // Validate all required fields are present\n const requiredFields = ['keyData', 'signature', 'keyType', 'timestamp', 'version'];\n const missingFields = requiredFields.filter(field => !signedPackage[field]);\n\n if (missingFields.length > 0) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Missing required fields in signed package', {\n missingFields: missingFields,\n availableFields: Object.keys(signedPackage)\n });\n throw new Error(`Required fields are missing in the signed package: ${missingFields.join(', ')}`);\n }\n\n // SECURITY ENHANCEMENT: MANDATORY signature verification for signed packages\n if (!verifyingKey) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'SECURITY VIOLATION: Signed package received without verifying key', {\n keyType: signedPackage.keyType,\n keySize: signedPackage.keyData.length,\n timestamp: signedPackage.timestamp,\n version: signedPackage.version,\n securityRisk: 'HIGH - Potential MITM attack vector'\n });\n\n // REJECT the signed package if no verifying key provided\n throw new Error('CRITICAL SECURITY ERROR: Signed key package received without a verification key. ' +\n 'This may indicate a possible MITM attack attempt. Import rejected for security reasons.');\n }\n\n // \u041E\u0411\u041D\u041E\u0412\u041B\u0415\u041D\u041E: \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u043C \u0443\u043B\u0443\u0447\u0448\u0435\u043D\u043D\u0443\u044E \u0432\u0430\u043B\u0438\u0434\u0430\u0446\u0438\u044E\n await EnhancedSecureCryptoUtils.validateKeyStructure(signedPackage.keyData, signedPackage.keyType || 'ECDH');\n\n // MANDATORY signature verification when verifyingKey is provided\n const packageCopy = { ...signedPackage };\n delete packageCopy.signature;\n const packageString = JSON.stringify(packageCopy);\n const isValidSignature = await EnhancedSecureCryptoUtils.verifySignature(verifyingKey, signedPackage.signature, packageString);\n\n if (!isValidSignature) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'SECURITY BREACH: Invalid signature detected - MITM attack prevented', {\n keyType: signedPackage.keyType,\n keySize: signedPackage.keyData.length,\n timestamp: signedPackage.timestamp,\n version: signedPackage.version,\n attackPrevented: true\n });\n throw new Error('CRITICAL SECURITY ERROR: Invalid key signature detected. ' +\n 'This indicates a possible MITM attack attempt. Key import rejected.');\n }\n\n // Additional MITM protection: Check for key reuse and suspicious patterns\n const keyFingerprint = await EnhancedSecureCryptoUtils.calculateKeyFingerprint(signedPackage.keyData);\n\n // Log successful verification with security details\n EnhancedSecureCryptoUtils.secureLog.log('info', 'SECURE: Signature verification passed for signed package', {\n keyType: signedPackage.keyType,\n keySize: signedPackage.keyData.length,\n timestamp: signedPackage.timestamp,\n version: signedPackage.version,\n signatureVerified: true,\n securityLevel: 'HIGH',\n keyFingerprint: keyFingerprint.substring(0, 8) // Only log first 8 chars for security\n });\n\n // Import the public key with fallback\n const keyBytes = new Uint8Array(signedPackage.keyData);\n const keyType = signedPackage.keyType || 'ECDH';\n\n // Try P-384 first\n try {\n const publicKey = await crypto.subtle.importKey(\n 'spki',\n keyBytes,\n {\n name: keyType,\n namedCurve: 'P-384'\n },\n false, // Non-extractable\n keyType === 'ECDSA' ? ['verify'] : []\n );\n\n // Use WeakMap to store metadata\n EnhancedSecureCryptoUtils._keyMetadata.set(publicKey, {\n trusted: true,\n verificationStatus: 'VERIFIED_SECURE',\n verificationTimestamp: Date.now()\n });\n\n return publicKey;\n } catch (p384Error) {\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'P-384 import failed, trying P-256', { error: p384Error.message });\n\n // Fallback to P-256\n const publicKey = await crypto.subtle.importKey(\n 'spki',\n keyBytes,\n {\n name: keyType,\n namedCurve: 'P-256'\n },\n false, // Non-extractable\n keyType === 'ECDSA' ? ['verify'] : []\n );\n\n // Use WeakMap to store metadata\n EnhancedSecureCryptoUtils._keyMetadata.set(publicKey, {\n trusted: true,\n verificationStatus: 'VERIFIED_SECURE',\n verificationTimestamp: Date.now()\n });\n\n return publicKey;\n }\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Signed package key import failed', {\n error: error.message,\n securityImplications: 'Potential security breach prevented'\n });\n throw new Error(`Failed to import the public key from the signed package: ${error.message}`);\n }\n }\n\n // Enhanced key derivation with metadata protection and 64-byte salt\n static async deriveSharedKeys(privateKey, publicKey, salt) {\n try {\n // Validate input parameters are CryptoKey instances\n if (!(privateKey instanceof CryptoKey)) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Private key is not a CryptoKey', {\n privateKeyType: typeof privateKey,\n privateKeyAlgorithm: privateKey?.algorithm?.name\n });\n throw new Error('The private key is not a valid CryptoKey.');\n }\n \n if (!(publicKey instanceof CryptoKey)) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Public key is not a CryptoKey', {\n publicKeyType: typeof publicKey,\n publicKeyAlgorithm: publicKey?.algorithm?.name\n });\n throw new Error('The private key is not a valid CryptoKey.');\n }\n \n // Validate salt size (should be 64 bytes for enhanced security)\n if (!salt || salt.length !== 64) {\n throw new Error('Salt must be exactly 64 bytes for enhanced security');\n }\n \n const saltBytes = new Uint8Array(salt);\n const encoder = new TextEncoder();\n \n // Enhanced context info with version and additional entropy\n const contextInfo = encoder.encode('SecureBit.chat v4.0 Enhanced Security Edition');\n \n // Derive master shared secret with enhanced parameters\n // Try SHA-384 first, fallback to SHA-256\n let sharedSecret;\n try {\n sharedSecret = await crypto.subtle.deriveKey(\n {\n name: 'ECDH',\n public: publicKey\n },\n privateKey,\n {\n name: 'HKDF',\n hash: 'SHA-384',\n salt: saltBytes,\n info: contextInfo\n },\n false, // Non-extractable\n ['deriveKey']\n );\n } catch (sha384Error) {\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'SHA-384 key derivation failed, trying SHA-256', { \n error: sha384Error.message,\n privateKeyType: typeof privateKey,\n publicKeyType: typeof publicKey,\n privateKeyAlgorithm: privateKey?.algorithm?.name,\n publicKeyAlgorithm: publicKey?.algorithm?.name\n });\n \n sharedSecret = await crypto.subtle.deriveKey(\n {\n name: 'ECDH',\n public: publicKey\n },\n privateKey,\n {\n name: 'HKDF',\n hash: 'SHA-256',\n salt: saltBytes,\n info: contextInfo\n },\n false, // Non-extractable\n ['deriveKey']\n );\n }\n\n // Derive message encryption key with fallback\n let encryptionKey;\n try {\n encryptionKey = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-384',\n salt: saltBytes,\n info: encoder.encode('message-encryption-v4')\n },\n sharedSecret,\n {\n name: 'AES-GCM',\n length: 256\n },\n false, // Non-extractable for enhanced security\n ['encrypt', 'decrypt']\n );\n } catch (sha384Error) {\n encryptionKey = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-256',\n salt: saltBytes,\n info: encoder.encode('message-encryption-v4')\n },\n sharedSecret,\n {\n name: 'AES-GCM',\n length: 256\n },\n false, // Non-extractable for enhanced security\n ['encrypt', 'decrypt']\n );\n }\n\n // Derive MAC key for message authentication with fallback\n let macKey;\n try {\n macKey = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-384',\n salt: saltBytes,\n info: encoder.encode('message-authentication-v4')\n },\n sharedSecret,\n {\n name: 'HMAC',\n hash: 'SHA-384'\n },\n false, // Non-extractable\n ['sign', 'verify']\n );\n } catch (sha384Error) {\n macKey = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-256',\n salt: saltBytes,\n info: encoder.encode('message-authentication-v4')\n },\n sharedSecret,\n {\n name: 'HMAC',\n hash: 'SHA-256'\n },\n false, // Non-extractable\n ['sign', 'verify']\n );\n }\n\n // Derive separate metadata encryption key with fallback\n let metadataKey;\n try {\n metadataKey = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-384',\n salt: saltBytes,\n info: encoder.encode('metadata-protection-v4')\n },\n sharedSecret,\n {\n name: 'AES-GCM',\n length: 256\n },\n false, // Non-extractable\n ['encrypt', 'decrypt']\n );\n } catch (sha384Error) {\n metadataKey = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-256',\n salt: saltBytes,\n info: encoder.encode('metadata-protection-v4')\n },\n sharedSecret,\n {\n name: 'AES-GCM',\n length: 256\n },\n false, // Non-extractable\n ['encrypt', 'decrypt']\n );\n }\n\n // Generate temporary extractable key for fingerprint calculation with fallback\n let fingerprintKey;\n try {\n fingerprintKey = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-384',\n salt: saltBytes,\n info: encoder.encode('fingerprint-generation-v4')\n },\n sharedSecret,\n {\n name: 'AES-GCM',\n length: 256\n },\n true, // Extractable only for fingerprint\n ['encrypt', 'decrypt']\n );\n } catch (sha384Error) {\n fingerprintKey = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-256',\n salt: saltBytes,\n info: encoder.encode('fingerprint-generation-v4')\n },\n sharedSecret,\n {\n name: 'AES-GCM',\n length: 256\n },\n true, // Extractable only for fingerprint\n ['encrypt', 'decrypt']\n );\n }\n\n // Generate key fingerprint for verification\n const fingerprintKeyData = await crypto.subtle.exportKey('raw', fingerprintKey);\n const fingerprint = await EnhancedSecureCryptoUtils.generateKeyFingerprint(Array.from(new Uint8Array(fingerprintKeyData)));\n\n // Validate that all derived keys are CryptoKey instances\n if (!(encryptionKey instanceof CryptoKey)) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Derived encryption key is not a CryptoKey', {\n encryptionKeyType: typeof encryptionKey,\n encryptionKeyAlgorithm: encryptionKey?.algorithm?.name\n });\n throw new Error('The derived encryption key is not a valid CryptoKey.');\n }\n \n if (!(macKey instanceof CryptoKey)) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Derived MAC key is not a CryptoKey', {\n macKeyType: typeof macKey,\n macKeyAlgorithm: macKey?.algorithm?.name\n });\n throw new Error('The derived MAC key is not a valid CryptoKey.');\n }\n \n if (!(metadataKey instanceof CryptoKey)) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Derived metadata key is not a CryptoKey', {\n metadataKeyType: typeof metadataKey,\n metadataKeyAlgorithm: metadataKey?.algorithm?.name\n });\n throw new Error('The derived metadata key is not a valid CryptoKey.');\n }\n\n EnhancedSecureCryptoUtils.secureLog.log('info', 'Enhanced shared keys derived successfully', {\n saltSize: salt.length,\n hasMetadataKey: true,\n nonExtractable: true,\n version: '4.0',\n allKeysValid: true\n });\n\n return {\n encryptionKey,\n macKey,\n metadataKey,\n fingerprint,\n timestamp: Date.now(),\n version: '4.0'\n };\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Enhanced key derivation failed', { error: error.message });\n throw new Error(`Failed to create shared encryption keys: ${error.message}`);\n }\n }\n\n static async generateKeyFingerprint(keyData) {\n const keyBuffer = new Uint8Array(keyData);\n const hashBuffer = await crypto.subtle.digest('SHA-384', keyBuffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.slice(0, 12).map(b => b.toString(16).padStart(2, '0')).join(':');\n }\n\n // Generate mutual authentication challenge\n static generateMutualAuthChallenge() {\n const challenge = crypto.getRandomValues(new Uint8Array(48)); // Increased to 48 bytes\n const timestamp = Date.now();\n const nonce = crypto.getRandomValues(new Uint8Array(16));\n \n return {\n challenge: Array.from(challenge),\n timestamp,\n nonce: Array.from(nonce),\n version: '4.0'\n };\n }\n\n // Create cryptographic proof for mutual authentication\n static async createAuthProof(challenge, privateKey, publicKey) {\n try {\n if (!challenge || !challenge.challenge || !challenge.timestamp || !challenge.nonce) {\n throw new Error('Invalid challenge structure');\n }\n \n // Check challenge age (max 2 minutes)\n const challengeAge = Date.now() - challenge.timestamp;\n if (challengeAge > 120000) {\n throw new Error('Challenge expired');\n }\n \n // Create proof data\n const proofData = {\n challenge: challenge.challenge,\n timestamp: challenge.timestamp,\n nonce: challenge.nonce,\n responseTimestamp: Date.now(),\n publicKeyHash: await EnhancedSecureCryptoUtils.hashPublicKey(publicKey)\n };\n \n // Sign the proof\n const proofString = JSON.stringify(proofData);\n const signature = await EnhancedSecureCryptoUtils.signData(privateKey, proofString);\n \n const proof = {\n ...proofData,\n signature,\n version: '4.0'\n };\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'Authentication proof created', {\n challengeAge: Math.round(challengeAge / 1000) + 's'\n });\n \n return proof;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Authentication proof creation failed', { error: error.message });\n throw new Error(`Failed to create cryptographic proof: ${error.message}`);\n }\n }\n\n // Verify mutual authentication proof\n static async verifyAuthProof(proof, challenge, publicKey) {\n try {\n await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 20) + 5));\n // Assert the public key is valid and has the correct usage\n EnhancedSecureCryptoUtils.assertCryptoKey(publicKey, 'ECDSA', ['verify']);\n\n if (!proof || !challenge || !publicKey) {\n throw new Error('Missing required parameters for proof verification');\n }\n\n // Validate proof structure\n const requiredFields = ['challenge', 'timestamp', 'nonce', 'responseTimestamp', 'publicKeyHash', 'signature'];\n for (const field of requiredFields) {\n if (!proof[field]) {\n throw new Error(`Missing required field: ${field}`);\n }\n }\n\n // Verify challenge matches\n if (!EnhancedSecureCryptoUtils.constantTimeCompareArrays(proof.challenge, challenge.challenge) ||\n proof.timestamp !== challenge.timestamp ||\n !EnhancedSecureCryptoUtils.constantTimeCompareArrays(proof.nonce, challenge.nonce)) {\n throw new Error('Challenge mismatch - possible replay attack');\n }\n\n // Check response time (max 5 minutes)\n const responseAge = Date.now() - proof.responseTimestamp;\n if (responseAge > 300000) {\n throw new Error('Proof response expired');\n }\n\n // Verify public key hash\n const expectedHash = await EnhancedSecureCryptoUtils.hashPublicKey(publicKey);\n if (!EnhancedSecureCryptoUtils.constantTimeCompare(proof.publicKeyHash, expectedHash)) {\n throw new Error('Public key hash mismatch');\n }\n\n // Verify signature\n const proofCopy = { ...proof };\n delete proofCopy.signature;\n const proofString = JSON.stringify(proofCopy);\n const isValidSignature = await EnhancedSecureCryptoUtils.verifySignature(publicKey, proof.signature, proofString);\n\n if (!isValidSignature) {\n throw new Error('Invalid proof signature');\n }\n\n EnhancedSecureCryptoUtils.secureLog.log('info', 'Authentication proof verified successfully', {\n responseAge: Math.round(responseAge / 1000) + 's'\n });\n\n return true;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Authentication proof verification failed', { error: error.message });\n throw new Error(`Failed to verify cryptographic proof: ${error.message}`);\n }\n }\n\n // Hash public key for verification\n static async hashPublicKey(publicKey) {\n try {\n const exported = await crypto.subtle.exportKey('spki', publicKey);\n const hash = await crypto.subtle.digest('SHA-384', exported);\n const hashArray = Array.from(new Uint8Array(hash));\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Public key hashing failed', { error: error.message });\n throw new Error('Failed to create hash of the public key');\n }\n }\n\n // Legacy authentication challenge for backward compatibility\n static generateAuthChallenge() {\n const challenge = crypto.getRandomValues(new Uint8Array(32));\n return Array.from(challenge);\n }\n\n // Generate verification code for out-of-band authentication\n static generateVerificationCode() {\n const chars = '0123456789ABCDEF';\n let result = '';\n const values = crypto.getRandomValues(new Uint8Array(6));\n for (let i = 0; i < 6; i++) {\n result += chars[values[i] % chars.length];\n }\n return result.match(/.{1,2}/g).join('-');\n }\n\n // Enhanced message encryption with metadata protection and sequence numbers\n static async encryptMessage(message, encryptionKey, macKey, metadataKey, messageId, sequenceNumber = 0) {\n try {\n if (!message || typeof message !== 'string') {\n throw new Error('Invalid message format');\n }\n\n EnhancedSecureCryptoUtils.assertCryptoKey(encryptionKey, 'AES-GCM', ['encrypt']);\n EnhancedSecureCryptoUtils.assertCryptoKey(macKey, 'HMAC', ['sign']);\n EnhancedSecureCryptoUtils.assertCryptoKey(metadataKey, 'AES-GCM', ['encrypt']);\n\n const encoder = new TextEncoder();\n const messageData = encoder.encode(message);\n const messageIv = crypto.getRandomValues(new Uint8Array(12));\n const metadataIv = crypto.getRandomValues(new Uint8Array(12));\n const timestamp = Date.now();\n\n const paddingSize = 16 - (messageData.length % 16);\n const paddedMessage = new Uint8Array(messageData.length + paddingSize);\n paddedMessage.set(messageData);\n const padding = crypto.getRandomValues(new Uint8Array(paddingSize));\n paddedMessage.set(padding, messageData.length);\n\n const encryptedMessage = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: messageIv },\n encryptionKey,\n paddedMessage\n );\n\n const metadata = {\n id: messageId,\n timestamp: timestamp,\n sequenceNumber: sequenceNumber,\n originalLength: messageData.length,\n version: '4.0'\n };\n\n const metadataStr = JSON.stringify(EnhancedSecureCryptoUtils.sortObjectKeys(metadata));\n const encryptedMetadata = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: metadataIv },\n metadataKey,\n encoder.encode(metadataStr)\n );\n\n const payload = {\n messageIv: Array.from(messageIv),\n messageData: Array.from(new Uint8Array(encryptedMessage)),\n metadataIv: Array.from(metadataIv),\n metadataData: Array.from(new Uint8Array(encryptedMetadata)),\n version: '4.0'\n };\n\n const sortedPayload = EnhancedSecureCryptoUtils.sortObjectKeys(payload);\n const payloadStr = JSON.stringify(sortedPayload);\n\n const mac = await crypto.subtle.sign(\n 'HMAC',\n macKey,\n encoder.encode(payloadStr)\n );\n\n payload.mac = Array.from(new Uint8Array(mac));\n\n EnhancedSecureCryptoUtils.secureLog.log('info', 'Message encrypted with metadata protection', {\n messageId,\n sequenceNumber,\n hasMetadataProtection: true,\n hasPadding: true\n });\n\n return payload;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Message encryption failed', {\n error: error.message,\n messageId\n });\n throw new Error(`Failed to encrypt the message: ${error.message}`);\n }\n }\n\n // Enhanced message decryption with metadata protection and sequence validation\n static async decryptMessage(encryptedPayload, encryptionKey, macKey, metadataKey, expectedSequenceNumber = null) {\n try {\n EnhancedSecureCryptoUtils.assertCryptoKey(encryptionKey, 'AES-GCM', ['decrypt']);\n EnhancedSecureCryptoUtils.assertCryptoKey(macKey, 'HMAC', ['verify']);\n EnhancedSecureCryptoUtils.assertCryptoKey(metadataKey, 'AES-GCM', ['decrypt']);\n\n const requiredFields = ['messageIv', 'messageData', 'metadataIv', 'metadataData', 'mac', 'version'];\n for (const field of requiredFields) {\n if (!encryptedPayload[field]) {\n throw new Error(`Missing required field: ${field}`);\n }\n }\n\n const payloadCopy = { ...encryptedPayload };\n delete payloadCopy.mac;\n const sortedPayloadCopy = EnhancedSecureCryptoUtils.sortObjectKeys(payloadCopy);\n const payloadStr = JSON.stringify(sortedPayloadCopy);\n\n const macValid = await crypto.subtle.verify(\n 'HMAC',\n macKey,\n new Uint8Array(encryptedPayload.mac),\n new TextEncoder().encode(payloadStr)\n );\n\n if (!macValid) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'MAC verification failed', {\n payloadFields: Object.keys(encryptedPayload),\n macLength: encryptedPayload.mac?.length\n });\n throw new Error('Message authentication failed - possible tampering');\n }\n\n const metadataIv = new Uint8Array(encryptedPayload.metadataIv);\n const metadataData = new Uint8Array(encryptedPayload.metadataData);\n\n const decryptedMetadataBuffer = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: metadataIv },\n metadataKey,\n metadataData\n );\n\n const metadataStr = new TextDecoder().decode(decryptedMetadataBuffer);\n const metadata = JSON.parse(metadataStr);\n\n if (!metadata.id || !metadata.timestamp || metadata.sequenceNumber === undefined || !metadata.originalLength) {\n throw new Error('Invalid metadata structure');\n }\n\n const messageAge = Date.now() - metadata.timestamp;\n if (messageAge > 300000) {\n throw new Error('Message expired (older than 5 minutes)');\n }\n\n if (expectedSequenceNumber !== null) {\n if (metadata.sequenceNumber < expectedSequenceNumber) {\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'Received message with lower sequence number, possible queued message', {\n expected: expectedSequenceNumber,\n received: metadata.sequenceNumber,\n messageId: metadata.id\n });\n } else if (metadata.sequenceNumber > expectedSequenceNumber + 10) {\n throw new Error(`Sequence number gap too large: expected around ${expectedSequenceNumber}, got ${metadata.sequenceNumber}`);\n }\n }\n\n const messageIv = new Uint8Array(encryptedPayload.messageIv);\n const messageData = new Uint8Array(encryptedPayload.messageData);\n\n const decryptedMessageBuffer = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: messageIv },\n encryptionKey,\n messageData\n );\n\n const paddedMessage = new Uint8Array(decryptedMessageBuffer);\n const originalMessage = paddedMessage.slice(0, metadata.originalLength);\n\n const decoder = new TextDecoder();\n const message = decoder.decode(originalMessage);\n\n EnhancedSecureCryptoUtils.secureLog.log('info', 'Message decrypted successfully', {\n messageId: metadata.id,\n sequenceNumber: metadata.sequenceNumber,\n messageAge: Math.round(messageAge / 1000) + 's'\n });\n\n return {\n message: message,\n messageId: metadata.id,\n timestamp: metadata.timestamp,\n sequenceNumber: metadata.sequenceNumber\n };\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Message decryption failed', { error: error.message });\n throw new Error(`Failed to decrypt the message: ${error.message}`);\n }\n }\n\n // Enhanced input sanitization\n static sanitizeMessage(message) {\n if (typeof message !== 'string') {\n throw new Error('Message must be a string');\n }\n \n return message\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/javascript:/gi, '')\n .replace(/data:/gi, '')\n .replace(/vbscript:/gi, '')\n .replace(/onload\\s*=/gi, '')\n .replace(/onerror\\s*=/gi, '')\n .replace(/onclick\\s*=/gi, '')\n .trim()\n .substring(0, 2000); // Increased limit\n }\n\n // Generate cryptographically secure salt (64 bytes for enhanced security)\n static generateSalt() {\n return Array.from(crypto.getRandomValues(new Uint8Array(64)));\n }\n\n // Calculate key fingerprint for MITM protection\n static async calculateKeyFingerprint(keyData) {\n try {\n const encoder = new TextEncoder();\n const keyBytes = new Uint8Array(keyData);\n \n // Create a hash of the key data for fingerprinting\n const hashBuffer = await crypto.subtle.digest('SHA-256', keyBytes);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n \n // Convert to hexadecimal string\n const fingerprint = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n \n EnhancedSecureCryptoUtils.secureLog.log('info', 'Key fingerprint calculated', {\n keySize: keyData.length,\n fingerprintLength: fingerprint.length\n });\n \n return fingerprint;\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Key fingerprint calculation failed', { error: error.message });\n throw new Error('Failed to compute the key fingerprint');\n }\n }\n\n static constantTimeCompare(a, b) {\n const strA = typeof a === 'string' ? a : JSON.stringify(a);\n const strB = typeof b === 'string' ? b : JSON.stringify(b);\n \n if (strA.length !== strB.length) {\n let dummy = 0;\n for (let i = 0; i < Math.max(strA.length, strB.length); i++) {\n dummy |= (strA.charCodeAt(i % strA.length) || 0) ^ (strB.charCodeAt(i % strB.length) || 0);\n }\n return false;\n }\n \n let result = 0;\n for (let i = 0; i < strA.length; i++) {\n result |= strA.charCodeAt(i) ^ strB.charCodeAt(i);\n }\n \n return result === 0;\n }\n\n static constantTimeCompareArrays(arr1, arr2) {\n if (!Array.isArray(arr1) || !Array.isArray(arr2)) {\n return false;\n }\n \n if (arr1.length !== arr2.length) {\n let dummy = 0;\n const maxLen = Math.max(arr1.length, arr2.length);\n for (let i = 0; i < maxLen; i++) {\n dummy |= (arr1[i % arr1.length] || 0) ^ (arr2[i % arr2.length] || 0);\n }\n return false;\n }\n \n let result = 0;\n for (let i = 0; i < arr1.length; i++) {\n result |= arr1[i] ^ arr2[i];\n }\n \n return result === 0;\n }\n \n /**\n * CRITICAL SECURITY: Encrypt data with AAD (Additional Authenticated Data)\n * This method provides authenticated encryption with additional data binding\n */\n static async encryptDataWithAAD(data, key, aad) {\n try {\n const dataString = typeof data === 'string' ? data : JSON.stringify(data);\n const encoder = new TextEncoder();\n const dataBuffer = encoder.encode(dataString);\n const aadBuffer = encoder.encode(aad);\n\n // Generate random IV\n const iv = crypto.getRandomValues(new Uint8Array(12));\n\n // Encrypt with AAD\n const encrypted = await crypto.subtle.encrypt(\n { \n name: 'AES-GCM', \n iv: iv,\n additionalData: aadBuffer\n },\n key,\n dataBuffer\n );\n\n // Package encrypted data\n const encryptedPackage = {\n version: '1.0',\n iv: Array.from(iv),\n data: Array.from(new Uint8Array(encrypted)),\n aad: aad,\n timestamp: Date.now()\n };\n\n const packageString = JSON.stringify(encryptedPackage);\n const packageBuffer = encoder.encode(packageString);\n \n return EnhancedSecureCryptoUtils.arrayBufferToBase64(packageBuffer);\n } catch (error) {\n throw new Error(`AAD encryption failed: ${error.message}`);\n }\n }\n\n /**\n * CRITICAL SECURITY: Decrypt data with AAD validation\n * This method provides authenticated decryption with additional data validation\n */\n static async decryptDataWithAAD(encryptedData, key, expectedAad) {\n try {\n const packageBuffer = EnhancedSecureCryptoUtils.base64ToArrayBuffer(encryptedData);\n const packageString = new TextDecoder().decode(packageBuffer);\n const encryptedPackage = JSON.parse(packageString);\n\n if (!encryptedPackage.version || !encryptedPackage.iv || !encryptedPackage.data || !encryptedPackage.aad) {\n throw new Error('Invalid encrypted data format');\n }\n\n // Validate AAD matches expected\n if (encryptedPackage.aad !== expectedAad) {\n throw new Error('AAD mismatch - possible tampering or replay attack');\n }\n\n const iv = new Uint8Array(encryptedPackage.iv);\n const encrypted = new Uint8Array(encryptedPackage.data);\n const aadBuffer = new TextEncoder().encode(encryptedPackage.aad);\n\n // Decrypt with AAD validation\n const decrypted = await crypto.subtle.decrypt(\n { \n name: 'AES-GCM', \n iv: iv,\n additionalData: aadBuffer\n },\n key,\n encrypted\n );\n\n const decryptedString = new TextDecoder().decode(decrypted);\n\n try {\n return JSON.parse(decryptedString);\n } catch {\n return decryptedString;\n }\n } catch (error) {\n throw new Error(`AAD decryption failed: ${error.message}`);\n }\n }\n\n // Initialize secure logging system after class definition\n static {\n if (EnhancedSecureCryptoUtils.secureLog && typeof EnhancedSecureCryptoUtils.secureLog.init === 'function') {\n EnhancedSecureCryptoUtils.secureLog.init();\n }\n }\n}\n\nexport { EnhancedSecureCryptoUtils };", "// ============================================\n// SECURE FILE TRANSFER CONTEXT\n// ============================================\nclass SecureFileTransferContext {\n static #instance = null;\n static #contextKey = Symbol('SecureFileTransferContext');\n \n static getInstance() {\n if (!this.#instance) {\n this.#instance = new SecureFileTransferContext();\n }\n return this.#instance;\n }\n \n #fileTransferSystem = null;\n #active = false;\n #securityLevel = 'high';\n \n setFileTransferSystem(system) {\n if (!(system instanceof EnhancedSecureFileTransfer)) {\n throw new Error('Invalid file transfer system instance');\n }\n this.#fileTransferSystem = system;\n this.#active = true;\n console.log('\uD83D\uDD12 Secure file transfer context initialized');\n }\n \n getFileTransferSystem() {\n return this.#fileTransferSystem;\n }\n \n isActive() {\n return this.#active && this.#fileTransferSystem !== null;\n }\n \n deactivate() {\n this.#active = false;\n this.#fileTransferSystem = null;\n console.log('\uD83D\uDD12 Secure file transfer context deactivated');\n }\n \n getSecurityLevel() {\n return this.#securityLevel;\n }\n \n setSecurityLevel(level) {\n if (['low', 'medium', 'high'].includes(level)) {\n this.#securityLevel = level;\n }\n }\n}\n\n// ============================================\n// SECURITY ERROR HANDLER\n// ============================================\n\nclass SecurityErrorHandler {\n static #allowedErrors = new Set([\n 'File size exceeds maximum limit',\n 'Unsupported file type',\n 'Transfer timeout',\n 'Connection lost',\n 'Invalid file data',\n 'File transfer failed',\n 'Transfer cancelled',\n 'Network error',\n 'File not found',\n 'Permission denied'\n ]);\n \n static sanitizeError(error) {\n const message = error.message || error;\n\n for (const allowed of this.#allowedErrors) {\n if (message.includes(allowed)) {\n return allowed;\n }\n }\n\n console.error('\uD83D\uDD12 Internal file transfer error:', {\n message: error.message,\n stack: error.stack,\n timestamp: new Date().toISOString()\n });\n\n return 'File transfer failed';\n }\n \n static logSecurityEvent(event, details = {}) {\n console.warn('\uD83D\uDD12 Security event:', {\n event,\n timestamp: new Date().toISOString(),\n ...details\n });\n }\n}\n\n// ============================================\n// FILE METADATA SIGNATURE SYSTEM\n// ============================================\n\nclass FileMetadataSigner {\n static async signFileMetadata(metadata, privateKey) {\n try {\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify({\n fileId: metadata.fileId,\n fileName: metadata.fileName,\n fileSize: metadata.fileSize,\n fileHash: metadata.fileHash,\n timestamp: metadata.timestamp,\n version: metadata.version || '2.0'\n }));\n \n const signature = await crypto.subtle.sign(\n 'RSASSA-PKCS1-v1_5',\n privateKey,\n data\n );\n \n return Array.from(new Uint8Array(signature));\n } catch (error) {\n SecurityErrorHandler.logSecurityEvent('signature_failed', { error: error.message });\n throw new Error('Failed to sign file metadata');\n }\n }\n \n static async verifyFileMetadata(metadata, signature, publicKey) {\n try {\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify({\n fileId: metadata.fileId,\n fileName: metadata.fileName,\n fileSize: metadata.fileSize,\n fileHash: metadata.fileHash,\n timestamp: metadata.timestamp,\n version: metadata.version || '2.0'\n }));\n \n const signatureBuffer = new Uint8Array(signature);\n \n const isValid = await crypto.subtle.verify(\n 'RSASSA-PKCS1-v1_5',\n publicKey,\n signatureBuffer,\n data\n );\n \n if (!isValid) {\n SecurityErrorHandler.logSecurityEvent('invalid_signature', { fileId: metadata.fileId });\n }\n \n return isValid;\n } catch (error) {\n SecurityErrorHandler.logSecurityEvent('verification_failed', { error: error.message });\n return false;\n }\n }\n}\n\n// ============================================\n// \u0422\u041E\u0427\u041D\u042B\u0415 \u0418\u0421\u041F\u0420\u0410\u0412\u041B\u0415\u041D\u0418\u042F \u0411\u0415\u0417\u041E\u041F\u0410\u0421\u041D\u041E\u0421\u0422\u0418\n// ============================================\n\nclass MessageSizeValidator {\n static MAX_MESSAGE_SIZE = 1024 * 1024; // 1MB\n \n static isMessageSizeValid(message) {\n const messageString = JSON.stringify(message);\n const sizeInBytes = new Blob([messageString]).size;\n \n if (sizeInBytes > this.MAX_MESSAGE_SIZE) {\n SecurityErrorHandler.logSecurityEvent('message_too_large', {\n size: sizeInBytes,\n limit: this.MAX_MESSAGE_SIZE\n });\n throw new Error('Message too large');\n }\n \n return true;\n }\n}\n\nclass AtomicOperations {\n constructor() {\n this.locks = new Map();\n }\n \n async withLock(key, operation) {\n if (this.locks.has(key)) {\n await this.locks.get(key);\n }\n \n const lockPromise = (async () => {\n try {\n return await operation();\n } finally {\n this.locks.delete(key);\n }\n })();\n \n this.locks.set(key, lockPromise);\n return lockPromise;\n }\n}\n\n// Rate limiting \u0434\u043B\u044F \u0437\u0430\u0449\u0438\u0442\u044B \u043E\u0442 \u0441\u043F\u0430\u043C\u0430\nclass RateLimiter {\n constructor(maxRequests, windowMs) {\n this.maxRequests = maxRequests;\n this.windowMs = windowMs;\n this.requests = new Map();\n }\n \n isAllowed(identifier) {\n const now = Date.now();\n const windowStart = now - this.windowMs;\n \n if (!this.requests.has(identifier)) {\n this.requests.set(identifier, []);\n }\n \n const userRequests = this.requests.get(identifier);\n \n const validRequests = userRequests.filter(time => time > windowStart);\n this.requests.set(identifier, validRequests);\n \n if (validRequests.length >= this.maxRequests) {\n SecurityErrorHandler.logSecurityEvent('rate_limit_exceeded', {\n identifier,\n requestCount: validRequests.length,\n limit: this.maxRequests\n });\n return false;\n }\n \n validRequests.push(now);\n return true;\n }\n}\n\nclass SecureMemoryManager {\n static secureWipe(buffer) {\n if (buffer instanceof ArrayBuffer) {\n const view = new Uint8Array(buffer);\n crypto.getRandomValues(view);\n } else if (buffer instanceof Uint8Array) {\n crypto.getRandomValues(buffer);\n }\n }\n \n static secureDelete(obj, prop) {\n if (obj[prop]) {\n this.secureWipe(obj[prop]);\n delete obj[prop];\n }\n }\n}\n\nclass EnhancedSecureFileTransfer {\n constructor(webrtcManager, onProgress, onComplete, onError, onFileReceived) {\n this.webrtcManager = webrtcManager;\n this.onProgress = onProgress;\n this.onComplete = onComplete;\n this.onError = onError;\n this.onFileReceived = onFileReceived;\n \n // Validate webrtcManager\n if (!webrtcManager) {\n throw new Error('webrtcManager is required for EnhancedSecureFileTransfer');\n }\n \n SecureFileTransferContext.getInstance().setFileTransferSystem(this);\n \n this.atomicOps = new AtomicOperations();\n this.rateLimiter = new RateLimiter(10, 60000);\n\n this.signingKey = null;\n this.verificationKey = null;\n \n // Transfer settings\n this.CHUNK_SIZE = 64 * 1024; // 64 KB\n this.MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 MB limit\n this.MAX_CONCURRENT_TRANSFERS = 3;\n this.CHUNK_TIMEOUT = 30000; // 30 seconds per chunk\n this.RETRY_ATTEMPTS = 3;\n\n this.FILE_TYPE_RESTRICTIONS = {\n documents: {\n extensions: ['.pdf', '.doc', '.docx', '.txt', '.md', '.rtf', '.odt'],\n mimeTypes: [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'text/plain',\n 'text/markdown',\n 'application/rtf',\n 'application/vnd.oasis.opendocument.text'\n ],\n maxSize: 50 * 1024 * 1024, // 50 MB\n category: 'Documents',\n description: 'PDF, DOC, TXT, MD, RTF, ODT'\n },\n \n images: {\n extensions: ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.svg', '.ico'],\n mimeTypes: [\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/bmp',\n 'image/svg+xml',\n 'image/x-icon'\n ],\n maxSize: 25 * 1024 * 1024, // 25 MB\n category: 'Images',\n description: 'JPG, PNG, GIF, WEBP, BMP, SVG, ICO'\n },\n \n archives: {\n extensions: ['.zip', '.rar', '.7z', '.tar', '.gz', '.bz2', '.xz'],\n mimeTypes: [\n 'application/zip',\n 'application/x-rar-compressed',\n 'application/x-7z-compressed',\n 'application/x-tar',\n 'application/gzip',\n 'application/x-bzip2',\n 'application/x-xz'\n ],\n maxSize: 100 * 1024 * 1024, // 100 MB\n category: 'Archives',\n description: 'ZIP, RAR, 7Z, TAR, GZ, BZ2, XZ'\n },\n \n media: {\n extensions: ['.mp3', '.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm', '.ogg', '.wav'],\n mimeTypes: [\n 'audio/mpeg',\n 'video/mp4',\n 'video/x-msvideo',\n 'video/x-matroska',\n 'video/quicktime',\n 'video/x-ms-wmv',\n 'video/x-flv',\n 'video/webm',\n 'audio/ogg',\n 'audio/wav'\n ],\n maxSize: 100 * 1024 * 1024, // 100 MB\n category: 'Media',\n description: 'MP3, MP4, AVI, MKV, MOV, WMV, FLV, WEBM, OGG, WAV'\n },\n \n general: {\n extensions: [], \n mimeTypes: [], \n maxSize: 50 * 1024 * 1024, // 50 MB\n category: 'General',\n description: 'Any file type up to size limits'\n }\n };\n \n // Active transfers tracking\n this.activeTransfers = new Map(); // fileId -> transfer state\n this.receivingTransfers = new Map(); // fileId -> receiving state\n this.transferQueue = []; // Queue for pending transfers\n this.pendingChunks = new Map();\n \n // Session key derivation\n this.sessionKeys = new Map(); // fileId -> derived session key\n \n // Security\n this.processedChunks = new Set(); // Prevent replay attacks\n this.transferNonces = new Map(); // fileId -> current nonce counter\n this.receivedFileBuffers = new Map(); // fileId -> { buffer:ArrayBuffer, type:string, name:string, size:number }\n\n this.setupFileMessageHandlers();\n\n if (this.webrtcManager) {\n this.webrtcManager.fileTransferSystem = this;\n }\n }\n\n // ============================================\n // FILE TYPE VALIDATION SYSTEM\n // ============================================\n\n getFileType(file) {\n const fileName = file.name.toLowerCase();\n const fileExtension = fileName.substring(fileName.lastIndexOf('.'));\n const mimeType = file.type.toLowerCase();\n\n for (const [typeKey, typeConfig] of Object.entries(this.FILE_TYPE_RESTRICTIONS)) {\n if (typeKey === 'general') continue; // \u041F\u0440\u043E\u043F\u0443\u0441\u043A\u0430\u0435\u043C \u043E\u0431\u0449\u0438\u0439 \u0442\u0438\u043F\n\n if (typeConfig.extensions.includes(fileExtension)) {\n return {\n type: typeKey,\n category: typeConfig.category,\n description: typeConfig.description,\n maxSize: typeConfig.maxSize,\n allowed: true\n };\n }\n\n if (typeConfig.mimeTypes.includes(mimeType)) {\n return {\n type: typeKey,\n category: typeConfig.category,\n description: typeConfig.description,\n maxSize: typeConfig.maxSize,\n allowed: true\n };\n }\n }\n\n const generalConfig = this.FILE_TYPE_RESTRICTIONS.general;\n return {\n type: 'general',\n category: generalConfig.category,\n description: generalConfig.description,\n maxSize: generalConfig.maxSize,\n allowed: true\n };\n }\n\n validateFile(file) {\n const fileType = this.getFileType(file);\n const errors = [];\n\n if (file.size > fileType.maxSize) {\n errors.push(`File size (${this.formatFileSize(file.size)}) exceeds maximum allowed for ${fileType.category} (${this.formatFileSize(fileType.maxSize)})`);\n }\n\n if (!fileType.allowed) {\n errors.push(`File type not allowed. Supported types: ${fileType.description}`);\n }\n\n if (file.size > this.MAX_FILE_SIZE) {\n errors.push(`File size (${this.formatFileSize(file.size)}) exceeds general limit (${this.formatFileSize(this.MAX_FILE_SIZE)})`);\n }\n \n return {\n isValid: errors.length === 0,\n errors: errors,\n fileType: fileType,\n fileSize: file.size,\n formattedSize: this.formatFileSize(file.size)\n };\n }\n\n formatFileSize(bytes) {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n }\n\n getSupportedFileTypes() {\n const supportedTypes = {};\n \n for (const [typeKey, typeConfig] of Object.entries(this.FILE_TYPE_RESTRICTIONS)) {\n if (typeKey === 'general') continue;\n \n supportedTypes[typeKey] = {\n category: typeConfig.category,\n description: typeConfig.description,\n extensions: typeConfig.extensions,\n maxSize: this.formatFileSize(typeConfig.maxSize),\n maxSizeBytes: typeConfig.maxSize\n };\n }\n \n return supportedTypes;\n }\n\n getFileTypeInfo() {\n return {\n supportedTypes: this.getSupportedFileTypes(),\n generalMaxSize: this.formatFileSize(this.MAX_FILE_SIZE),\n generalMaxSizeBytes: this.MAX_FILE_SIZE,\n restrictions: this.FILE_TYPE_RESTRICTIONS\n };\n }\n\n // ============================================\n // ENCODING HELPERS (Base64 for efficient transport)\n // ============================================\n arrayBufferToBase64(buffer) {\n const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);\n let binary = '';\n const len = bytes.byteLength;\n for (let i = 0; i < len; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n\n base64ToUint8Array(base64) {\n const binaryString = atob(base64);\n const len = binaryString.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes;\n }\n\n // ============================================\n // PUBLIC ACCESSORS FOR RECEIVED FILES\n // ============================================\n getReceivedFileMeta(fileId) {\n const entry = this.receivedFileBuffers.get(fileId);\n if (!entry) return null;\n return { fileId, fileName: entry.name, fileSize: entry.size, mimeType: entry.type };\n }\n\n async getBlob(fileId) {\n const entry = this.receivedFileBuffers.get(fileId);\n if (!entry) return null;\n return new Blob([entry.buffer], { type: entry.type });\n }\n\n async getObjectURL(fileId) {\n const blob = await this.getBlob(fileId);\n if (!blob) return null;\n return URL.createObjectURL(blob);\n }\n\n revokeObjectURL(url) {\n try { URL.revokeObjectURL(url); } catch (_) {}\n }\n\n setupFileMessageHandlers() {\n if (!this.webrtcManager.dataChannel) {\n const setupRetry = setInterval(() => {\n if (this.webrtcManager.dataChannel) {\n clearInterval(setupRetry);\n this.setupMessageInterception();\n }\n }, 100);\n\n setTimeout(() => {\n clearInterval(setupRetry);\n }, 5000);\n \n return;\n }\n \n // \u0415\u0441\u043B\u0438 dataChannel \u0443\u0436\u0435 \u0433\u043E\u0442\u043E\u0432, \u0441\u0440\u0430\u0437\u0443 \u043D\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043C\n this.setupMessageInterception();\n }\n\n setupMessageInterception() {\n try {\n if (!this.webrtcManager.dataChannel) {\n return;\n }\n\n if (this.webrtcManager) {\n this.webrtcManager.fileTransferSystem = this;\n }\n\n if (this.webrtcManager.dataChannel.onmessage) {\n this.originalOnMessage = this.webrtcManager.dataChannel.onmessage;\n }\n\n this.webrtcManager.dataChannel.onmessage = async (event) => {\n try {\n if (event.data.length > MessageSizeValidator.MAX_MESSAGE_SIZE) {\n console.warn('\uD83D\uDD12 Message too large, ignoring');\n SecurityErrorHandler.logSecurityEvent('oversized_message_blocked');\n return;\n }\n \n if (typeof event.data === 'string') {\n try {\n const parsed = JSON.parse(event.data);\n \n MessageSizeValidator.isMessageSizeValid(parsed);\n \n if (this.isFileTransferMessage(parsed)) {\n await this.handleFileMessage(parsed);\n return; \n }\n } catch (parseError) {\n if (parseError.message === 'Message too large') {\n return; \n }\n }\n }\n\n if (this.originalOnMessage) {\n return this.originalOnMessage.call(this.webrtcManager.dataChannel, event);\n }\n } catch (error) {\n console.error('\u274C Error in file system message interception:', error);\n if (this.originalOnMessage) {\n return this.originalOnMessage.call(this.webrtcManager.dataChannel, event);\n }\n }\n };\n } catch (error) {\n console.error('\u274C Failed to set up message interception:', error);\n }\n }\n\n isFileTransferMessage(message) {\n if (!message || typeof message !== 'object' || !message.type) {\n return false;\n }\n \n const fileMessageTypes = [\n 'file_transfer_start',\n 'file_transfer_response', \n 'file_chunk',\n 'chunk_confirmation',\n 'file_transfer_complete',\n 'file_transfer_error'\n ];\n \n return fileMessageTypes.includes(message.type);\n }\n\n async handleFileMessage(message) {\n try {\n if (!this.webrtcManager.fileTransferSystem) {\n try {\n if (typeof this.webrtcManager.initializeFileTransfer === 'function') {\n this.webrtcManager.initializeFileTransfer();\n \n let attempts = 0;\n const maxAttempts = 50; \n while (!this.webrtcManager.fileTransferSystem && attempts < maxAttempts) {\n await new Promise(resolve => setTimeout(resolve, 100));\n attempts++;\n }\n \n if (!this.webrtcManager.fileTransferSystem) {\n throw new Error('File transfer system initialization timeout');\n }\n } else {\n throw new Error('initializeFileTransfer method not available');\n }\n } catch (initError) {\n console.error('\u274C Failed to initialize file transfer system:', initError);\n if (message.fileId) {\n const errorMessage = {\n type: 'file_transfer_error',\n fileId: message.fileId,\n error: 'File transfer system not available',\n timestamp: Date.now()\n };\n await this.sendSecureMessage(errorMessage);\n }\n return;\n }\n }\n \n switch (message.type) {\n case 'file_transfer_start':\n await this.handleFileTransferStart(message);\n break;\n \n case 'file_transfer_response':\n this.handleTransferResponse(message);\n break;\n \n case 'file_chunk':\n await this.handleFileChunk(message);\n break;\n \n case 'chunk_confirmation':\n this.handleChunkConfirmation(message);\n break;\n \n case 'file_transfer_complete':\n this.handleTransferComplete(message);\n break;\n \n case 'file_transfer_error':\n this.handleTransferError(message);\n break;\n \n default:\n console.warn('\u26A0\uFE0F Unknown file message type:', message.type);\n }\n \n } catch (error) {\n console.error('\u274C Error handling file message:', error);\n\n if (message.fileId) {\n const errorMessage = {\n type: 'file_transfer_error',\n fileId: message.fileId,\n error: error.message,\n timestamp: Date.now()\n };\n await this.sendSecureMessage(errorMessage);\n }\n }\n }\n\n // ============================================\n // SIMPLIFIED KEY DERIVATION - USE SHARED DATA\n // ============================================\n\n async deriveFileSessionKey(fileId) {\n try {\n \n if (!this.webrtcManager.keyFingerprint || !this.webrtcManager.sessionSalt) {\n throw new Error('WebRTC session data not available');\n }\n\n const fileSalt = crypto.getRandomValues(new Uint8Array(32));\n\n const encoder = new TextEncoder();\n const fingerprintData = encoder.encode(this.webrtcManager.keyFingerprint);\n const fileIdData = encoder.encode(fileId);\n\n const sessionSaltArray = new Uint8Array(this.webrtcManager.sessionSalt);\n const combinedSeed = new Uint8Array(\n fingerprintData.length + \n sessionSaltArray.length + \n fileSalt.length + \n fileIdData.length\n );\n \n let offset = 0;\n combinedSeed.set(fingerprintData, offset);\n offset += fingerprintData.length;\n combinedSeed.set(sessionSaltArray, offset);\n offset += sessionSaltArray.length;\n combinedSeed.set(fileSalt, offset);\n offset += fileSalt.length;\n combinedSeed.set(fileIdData, offset);\n\n const keyMaterial = await crypto.subtle.digest('SHA-256', combinedSeed);\n\n const fileSessionKey = await crypto.subtle.importKey(\n 'raw',\n keyMaterial,\n { name: 'AES-GCM' },\n false,\n ['encrypt', 'decrypt']\n );\n\n this.sessionKeys.set(fileId, {\n key: fileSessionKey,\n salt: Array.from(fileSalt),\n created: Date.now()\n });\n\n return { key: fileSessionKey, salt: Array.from(fileSalt) };\n\n } catch (error) {\n console.error('\u274C Failed to derive file session key:', error);\n throw error;\n }\n }\n\n async deriveFileSessionKeyFromSalt(fileId, saltArray) {\n try {\n if (!saltArray || !Array.isArray(saltArray) || saltArray.length !== 32) {\n throw new Error(`Invalid salt: ${saltArray?.length || 0} bytes`);\n }\n \n if (!this.webrtcManager.keyFingerprint || !this.webrtcManager.sessionSalt) {\n throw new Error('WebRTC session data not available');\n }\n\n const encoder = new TextEncoder();\n const fingerprintData = encoder.encode(this.webrtcManager.keyFingerprint);\n const fileIdData = encoder.encode(fileId);\n\n const fileSalt = new Uint8Array(saltArray);\n const sessionSaltArray = new Uint8Array(this.webrtcManager.sessionSalt);\n\n const combinedSeed = new Uint8Array(\n fingerprintData.length + \n sessionSaltArray.length + \n fileSalt.length + \n fileIdData.length\n );\n \n let offset = 0;\n combinedSeed.set(fingerprintData, offset);\n offset += fingerprintData.length;\n combinedSeed.set(sessionSaltArray, offset);\n offset += sessionSaltArray.length;\n combinedSeed.set(fileSalt, offset);\n offset += fileSalt.length;\n combinedSeed.set(fileIdData, offset);\n\n const keyMaterial = await crypto.subtle.digest('SHA-256', combinedSeed);\n\n const fileSessionKey = await crypto.subtle.importKey(\n 'raw',\n keyMaterial,\n { name: 'AES-GCM' },\n false,\n ['encrypt', 'decrypt']\n );\n\n this.sessionKeys.set(fileId, {\n key: fileSessionKey,\n salt: saltArray,\n created: Date.now()\n });\n\n return fileSessionKey;\n\n } catch (error) {\n console.error('\u274C Failed to derive session key from salt:', error);\n throw error;\n }\n }\n\n // ============================================\n // FILE TRANSFER IMPLEMENTATION\n // ============================================\n\n async sendFile(file) {\n try {\n // Validate webrtcManager\n if (!this.webrtcManager) {\n throw new Error('WebRTC Manager not initialized');\n }\n\n const clientId = this.getClientIdentifier();\n if (!this.rateLimiter.isAllowed(clientId)) {\n SecurityErrorHandler.logSecurityEvent('rate_limit_exceeded', { clientId });\n throw new Error('Rate limit exceeded. Please wait before sending another file.');\n }\n\n if (!file || !file.size) {\n throw new Error('Invalid file object');\n }\n\n const validation = this.validateFile(file);\n if (!validation.isValid) {\n const errorMessage = validation.errors.join('. ');\n throw new Error(errorMessage);\n }\n\n if (this.activeTransfers.size >= this.MAX_CONCURRENT_TRANSFERS) {\n throw new Error('Maximum concurrent transfers reached');\n }\n\n // Generate unique file ID\n const fileId = `file_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n \n // Calculate file hash for integrity verification\n const fileHash = await this.calculateFileHash(file);\n \n // Derive session key for this file\n const keyResult = await this.deriveFileSessionKey(fileId);\n const sessionKey = keyResult.key;\n const salt = keyResult.salt;\n \n // Create transfer state\n const transferState = {\n fileId: fileId,\n file: file,\n fileHash: fileHash,\n sessionKey: sessionKey,\n salt: salt, \n totalChunks: Math.ceil(file.size / this.CHUNK_SIZE),\n sentChunks: 0,\n confirmedChunks: 0,\n startTime: Date.now(),\n status: 'preparing',\n retryCount: 0,\n lastChunkTime: Date.now()\n };\n\n this.activeTransfers.set(fileId, transferState);\n this.transferNonces.set(fileId, 0);\n\n // Send file metadata first\n await this.sendFileMetadata(transferState);\n \n // Start chunk transmission\n await this.startChunkTransmission(transferState);\n \n return fileId;\n\n } catch (error) {\n const safeError = SecurityErrorHandler.sanitizeError(error);\n console.error('\u274C File sending failed:', safeError);\n if (this.onError) this.onError(safeError);\n throw new Error(safeError);\n }\n }\n\n async sendFileMetadata(transferState) {\n try {\n const metadata = {\n type: 'file_transfer_start',\n fileId: transferState.fileId,\n fileName: transferState.file.name,\n fileSize: transferState.file.size,\n fileType: transferState.file.type || 'application/octet-stream',\n fileHash: transferState.fileHash,\n totalChunks: transferState.totalChunks,\n chunkSize: this.CHUNK_SIZE,\n salt: transferState.salt, \n timestamp: Date.now(),\n version: '2.0'\n };\n\n if (this.signingKey) {\n try {\n metadata.signature = await FileMetadataSigner.signFileMetadata(metadata, this.signingKey);\n console.log('\uD83D\uDD12 File metadata signed successfully');\n } catch (signError) {\n SecurityErrorHandler.logSecurityEvent('signature_failed', { \n fileId: transferState.fileId, \n error: signError.message \n });\n }\n }\n\n // Send metadata through secure channel\n await this.sendSecureMessage(metadata);\n \n transferState.status = 'metadata_sent';\n\n } catch (error) {\n const safeError = SecurityErrorHandler.sanitizeError(error);\n console.error('\u274C Failed to send file metadata:', safeError);\n transferState.status = 'failed';\n throw new Error(safeError);\n }\n }\n\n async startChunkTransmission(transferState) {\n try {\n transferState.status = 'transmitting';\n \n const file = transferState.file;\n const totalChunks = transferState.totalChunks;\n \n for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {\n const start = chunkIndex * this.CHUNK_SIZE;\n const end = Math.min(start + this.CHUNK_SIZE, file.size);\n \n // Read chunk from file\n const chunkData = await this.readFileChunk(file, start, end);\n \n // Send chunk (\u0441 \u0443\u0447\u0451\u0442\u043E\u043C backpressure)\n await this.sendFileChunk(transferState, chunkIndex, chunkData);\n \n // Update progress\n transferState.sentChunks++;\n const progress = Math.round((transferState.sentChunks / totalChunks) * 95) + 5; // 5-100%\n\n await this.waitForBackpressure();\n }\n \n transferState.status = 'waiting_confirmation';\n \n // Timeout for completion confirmation\n setTimeout(() => {\n if (this.activeTransfers.has(transferState.fileId)) {\n const state = this.activeTransfers.get(transferState.fileId);\n if (state.status === 'waiting_confirmation') {\n this.cleanupTransfer(transferState.fileId);\n }\n }\n }, 30000);\n \n } catch (error) {\n const safeError = SecurityErrorHandler.sanitizeError(error);\n console.error('\u274C Chunk transmission failed:', safeError);\n transferState.status = 'failed';\n throw new Error(safeError);\n }\n }\n\n async readFileChunk(file, start, end) {\n try {\n const blob = file.slice(start, end);\n return await blob.arrayBuffer();\n } catch (error) {\n const safeError = SecurityErrorHandler.sanitizeError(error);\n console.error('\u274C Failed to read file chunk:', safeError);\n throw new Error(safeError);\n }\n }\n\n async sendFileChunk(transferState, chunkIndex, chunkData) {\n try {\n const sessionKey = transferState.sessionKey;\n const nonce = crypto.getRandomValues(new Uint8Array(12));\n \n // Encrypt chunk data\n const encryptedChunk = await crypto.subtle.encrypt(\n {\n name: 'AES-GCM',\n iv: nonce\n },\n sessionKey,\n chunkData\n );\n \n // Use Base64 to drastically reduce JSON overhead\n const encryptedB64 = this.arrayBufferToBase64(new Uint8Array(encryptedChunk));\n const chunkMessage = {\n type: 'file_chunk',\n fileId: transferState.fileId,\n chunkIndex: chunkIndex,\n totalChunks: transferState.totalChunks,\n nonce: Array.from(nonce),\n encryptedDataB64: encryptedB64,\n chunkSize: chunkData.byteLength,\n timestamp: Date.now()\n };\n\n await this.waitForBackpressure();\n // Send chunk through secure channel\n await this.sendSecureMessage(chunkMessage);\n \n } catch (error) {\n const safeError = SecurityErrorHandler.sanitizeError(error);\n console.error('\u274C Failed to send file chunk:', safeError);\n throw new Error(safeError);\n }\n }\n\n async sendSecureMessage(message) {\n\n const messageString = JSON.stringify(message);\n const dc = this.webrtcManager?.dataChannel;\n const maxRetries = 10;\n let attempt = 0;\n const wait = (ms) => new Promise(r => setTimeout(r, ms));\n\n while (true) {\n try {\n if (!dc || dc.readyState !== 'open') {\n throw new Error('Data channel not ready');\n }\n await this.waitForBackpressure();\n dc.send(messageString);\n return; // success\n } catch (error) {\n const msg = String(error?.message || '');\n const queueFull = msg.includes('send queue is full') || msg.includes('bufferedAmount');\n const opErr = error?.name === 'OperationError';\n if ((queueFull || opErr) && attempt < maxRetries) {\n attempt++;\n await this.waitForBackpressure();\n await wait(Math.min(50 * attempt, 500));\n continue;\n }\n console.error('\u274C Failed to send secure message:', error);\n throw error;\n }\n }\n }\n\n async waitForBackpressure() {\n try {\n const dc = this.webrtcManager?.dataChannel;\n if (!dc) return;\n\n if (typeof dc.bufferedAmountLowThreshold === 'number') {\n if (dc.bufferedAmount > dc.bufferedAmountLowThreshold) {\n await new Promise(resolve => {\n const handler = () => {\n dc.removeEventListener('bufferedamountlow', handler);\n resolve();\n };\n dc.addEventListener('bufferedamountlow', handler, { once: true });\n });\n }\n return;\n }\n\n const softLimit = 4 * 1024 * 1024;\n while (dc.bufferedAmount > softLimit) {\n await new Promise(r => setTimeout(r, 20));\n }\n } catch (_) {\n // ignore\n }\n }\n\n async calculateFileHash(file) {\n try {\n const arrayBuffer = await file.arrayBuffer();\n const hashBuffer = await crypto.subtle.digest('SHA-256', arrayBuffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n } catch (error) {\n console.error('\u274C File hash calculation failed:', error);\n throw error;\n }\n }\n\n // ============================================\n // MESSAGE HANDLERS\n // ============================================\n\n async handleFileTransferStart(metadata) {\n try {\n // Validate metadata\n if (!metadata.fileId || !metadata.fileName || !metadata.fileSize) {\n throw new Error('Invalid file transfer metadata');\n }\n\n if (metadata.signature && this.verificationKey) {\n try {\n const isValid = await FileMetadataSigner.verifyFileMetadata(\n metadata, \n metadata.signature, \n this.verificationKey\n );\n \n if (!isValid) {\n SecurityErrorHandler.logSecurityEvent('invalid_metadata_signature', { \n fileId: metadata.fileId \n });\n throw new Error('Invalid file metadata signature');\n }\n \n console.log('\uD83D\uDD12 File metadata signature verified successfully');\n } catch (verifyError) {\n SecurityErrorHandler.logSecurityEvent('verification_failed', { \n fileId: metadata.fileId, \n error: verifyError.message \n });\n throw new Error('File metadata verification failed');\n }\n }\n \n // Check if we already have this transfer\n if (this.receivingTransfers.has(metadata.fileId)) {\n return;\n }\n \n // Derive session key from salt\n const sessionKey = await this.deriveFileSessionKeyFromSalt(\n metadata.fileId,\n metadata.salt\n );\n \n // Create receiving transfer state\n const receivingState = {\n fileId: metadata.fileId,\n fileName: metadata.fileName,\n fileSize: metadata.fileSize,\n fileType: metadata.fileType || 'application/octet-stream',\n fileHash: metadata.fileHash,\n totalChunks: metadata.totalChunks,\n chunkSize: metadata.chunkSize || this.CHUNK_SIZE,\n sessionKey: sessionKey,\n salt: metadata.salt,\n receivedChunks: new Map(),\n receivedCount: 0,\n startTime: Date.now(),\n lastChunkTime: Date.now(),\n status: 'receiving'\n };\n \n this.receivingTransfers.set(metadata.fileId, receivingState);\n \n // Send acceptance response\n const response = {\n type: 'file_transfer_response',\n fileId: metadata.fileId,\n accepted: true,\n timestamp: Date.now()\n };\n \n await this.sendSecureMessage(response);\n\n // Process buffered chunks if any\n if (this.pendingChunks.has(metadata.fileId)) {\n const bufferedChunks = this.pendingChunks.get(metadata.fileId);\n \n for (const [chunkIndex, chunkMessage] of bufferedChunks.entries()) {\n await this.handleFileChunk(chunkMessage);\n }\n \n this.pendingChunks.delete(metadata.fileId);\n }\n \n } catch (error) {\n const safeError = SecurityErrorHandler.sanitizeError(error);\n console.error('\u274C Failed to handle file transfer start:', safeError);\n \n // Send error response\n const errorResponse = {\n type: 'file_transfer_response',\n fileId: metadata.fileId,\n accepted: false,\n error: safeError, \n timestamp: Date.now()\n };\n await this.sendSecureMessage(errorResponse);\n }\n }\n\n async handleFileChunk(chunkMessage) {\n return this.atomicOps.withLock(\n `chunk-${chunkMessage.fileId}`, \n async () => {\n try {\n let receivingState = this.receivingTransfers.get(chunkMessage.fileId);\n \n // Buffer early chunks if transfer not yet initialized\n if (!receivingState) {\n if (!this.pendingChunks.has(chunkMessage.fileId)) {\n this.pendingChunks.set(chunkMessage.fileId, new Map());\n }\n \n this.pendingChunks.get(chunkMessage.fileId).set(chunkMessage.chunkIndex, chunkMessage);\n return;\n }\n \n // Update last chunk time\n receivingState.lastChunkTime = Date.now();\n \n // Check if chunk already received\n if (receivingState.receivedChunks.has(chunkMessage.chunkIndex)) {\n return;\n }\n \n // Validate chunk\n if (chunkMessage.chunkIndex < 0 || chunkMessage.chunkIndex >= receivingState.totalChunks) {\n throw new Error(`Invalid chunk index: ${chunkMessage.chunkIndex}`);\n }\n \n // Decrypt chunk\n const nonce = new Uint8Array(chunkMessage.nonce);\n // Backward compatible: prefer Base64, fallback to numeric array\n let encryptedData;\n if (chunkMessage.encryptedDataB64) {\n encryptedData = this.base64ToUint8Array(chunkMessage.encryptedDataB64);\n } else if (chunkMessage.encryptedData) {\n encryptedData = new Uint8Array(chunkMessage.encryptedData);\n } else {\n throw new Error('Missing encrypted data');\n }\n \n const decryptedChunk = await crypto.subtle.decrypt(\n {\n name: 'AES-GCM',\n iv: nonce\n },\n receivingState.sessionKey,\n encryptedData\n );\n \n // Verify chunk size\n if (decryptedChunk.byteLength !== chunkMessage.chunkSize) {\n throw new Error(`Chunk size mismatch: expected ${chunkMessage.chunkSize}, got ${decryptedChunk.byteLength}`);\n }\n \n // Store chunk\n receivingState.receivedChunks.set(chunkMessage.chunkIndex, decryptedChunk);\n receivingState.receivedCount++;\n \n // Send chunk confirmation\n const confirmation = {\n type: 'chunk_confirmation',\n fileId: chunkMessage.fileId,\n chunkIndex: chunkMessage.chunkIndex,\n timestamp: Date.now()\n };\n await this.sendSecureMessage(confirmation);\n \n // Check if all chunks received\n if (receivingState.receivedCount === receivingState.totalChunks) {\n await this.assembleFile(receivingState);\n }\n \n } catch (error) {\n const safeError = SecurityErrorHandler.sanitizeError(error);\n console.error('\u274C Failed to handle file chunk:', safeError);\n \n // Send error notification\n const errorMessage = {\n type: 'file_transfer_error',\n fileId: chunkMessage.fileId,\n error: safeError, \n chunkIndex: chunkMessage.chunkIndex,\n timestamp: Date.now()\n };\n await this.sendSecureMessage(errorMessage);\n \n // Mark transfer as failed\n const receivingState = this.receivingTransfers.get(chunkMessage.fileId);\n if (receivingState) {\n receivingState.status = 'failed';\n }\n \n if (this.onError) {\n this.onError(`Chunk processing failed: ${safeError}`);\n }\n }\n }\n );\n }\n\n async assembleFile(receivingState) {\n try {\n receivingState.status = 'assembling';\n \n // Verify we have all chunks\n for (let i = 0; i < receivingState.totalChunks; i++) {\n if (!receivingState.receivedChunks.has(i)) {\n throw new Error(`Missing chunk ${i}`);\n }\n }\n \n // Combine all chunks in order\n const chunks = [];\n for (let i = 0; i < receivingState.totalChunks; i++) {\n const chunk = receivingState.receivedChunks.get(i);\n chunks.push(new Uint8Array(chunk));\n }\n \n // Calculate total size\n const totalSize = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n \n // Verify total size matches expected\n if (totalSize !== receivingState.fileSize) {\n throw new Error(`File size mismatch: expected ${receivingState.fileSize}, got ${totalSize}`);\n }\n \n // Combine into single array\n const fileData = new Uint8Array(totalSize);\n let offset = 0;\n for (const chunk of chunks) {\n fileData.set(chunk, offset);\n offset += chunk.length;\n }\n \n // Verify file integrity\n const receivedHash = await this.calculateFileHashFromData(fileData);\n if (receivedHash !== receivingState.fileHash) {\n throw new Error('File integrity check failed - hash mismatch');\n }\n\n const fileBuffer = fileData.buffer;\n const fileBlob = new Blob([fileBuffer], { type: receivingState.fileType });\n \n receivingState.endTime = Date.now();\n receivingState.status = 'completed';\n\n this.receivedFileBuffers.set(receivingState.fileId, {\n buffer: fileBuffer,\n type: receivingState.fileType,\n name: receivingState.fileName,\n size: receivingState.fileSize\n });\n\n if (this.onFileReceived) {\n const getBlob = async () => new Blob([this.receivedFileBuffers.get(receivingState.fileId).buffer], { type: receivingState.fileType });\n const getObjectURL = async () => {\n const blob = await getBlob();\n return URL.createObjectURL(blob);\n };\n const revokeObjectURL = (url) => {\n try { URL.revokeObjectURL(url); } catch (_) {}\n };\n\n this.onFileReceived({\n fileId: receivingState.fileId,\n fileName: receivingState.fileName,\n fileSize: receivingState.fileSize,\n mimeType: receivingState.fileType,\n transferTime: receivingState.endTime - receivingState.startTime,\n // backward-compatibility for existing UIs\n fileBlob,\n getBlob,\n getObjectURL,\n revokeObjectURL\n });\n }\n \n // Send completion confirmation\n const completionMessage = {\n type: 'file_transfer_complete',\n fileId: receivingState.fileId,\n success: true,\n timestamp: Date.now()\n };\n await this.sendSecureMessage(completionMessage);\n \n // Cleanup\n if (this.receivingTransfers.has(receivingState.fileId)) {\n const rs = this.receivingTransfers.get(receivingState.fileId);\n if (rs && rs.receivedChunks) rs.receivedChunks.clear();\n }\n this.receivingTransfers.delete(receivingState.fileId);\n \n } catch (error) {\n console.error('\u274C File assembly failed:', error);\n receivingState.status = 'failed';\n \n if (this.onError) {\n this.onError(`File assembly failed: ${error.message}`);\n }\n \n // Send error notification\n const errorMessage = {\n type: 'file_transfer_complete',\n fileId: receivingState.fileId,\n success: false,\n error: error.message,\n timestamp: Date.now()\n };\n await this.sendSecureMessage(errorMessage);\n \n // Cleanup failed transfer\n this.cleanupReceivingTransfer(receivingState.fileId);\n }\n }\n\n async calculateFileHashFromData(data) {\n try {\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n } catch (error) {\n console.error('\u274C Hash calculation failed:', error);\n throw error;\n }\n }\n\n handleTransferResponse(response) {\n try {\n const transferState = this.activeTransfers.get(response.fileId);\n \n if (!transferState) {\n return;\n }\n \n if (response.accepted) {\n transferState.status = 'accepted';\n } else {\n transferState.status = 'rejected';\n \n if (this.onError) {\n this.onError(`Transfer rejected: ${response.error || 'Unknown reason'}`);\n }\n \n this.cleanupTransfer(response.fileId);\n }\n } catch (error) {\n console.error('\u274C Failed to handle transfer response:', error);\n }\n }\n\n handleChunkConfirmation(confirmation) {\n try {\n const transferState = this.activeTransfers.get(confirmation.fileId);\n if (!transferState) {\n return;\n }\n \n transferState.confirmedChunks++;\n transferState.lastChunkTime = Date.now();\n } catch (error) {\n console.error('\u274C Failed to handle chunk confirmation:', error);\n }\n }\n\n handleTransferComplete(completion) {\n try {\n const transferState = this.activeTransfers.get(completion.fileId);\n if (!transferState) {\n return;\n }\n \n if (completion.success) {\n transferState.status = 'completed';\n transferState.endTime = Date.now();\n \n if (this.onComplete) {\n this.onComplete({\n fileId: transferState.fileId,\n fileName: transferState.file.name,\n fileSize: transferState.file.size,\n transferTime: transferState.endTime - transferState.startTime,\n status: 'completed'\n });\n }\n } else {\n transferState.status = 'failed';\n \n if (this.onError) {\n this.onError(`Transfer failed: ${completion.error || 'Unknown error'}`);\n }\n }\n \n this.cleanupTransfer(completion.fileId);\n \n } catch (error) {\n console.error('\u274C Failed to handle transfer completion:', error);\n }\n }\n\n handleTransferError(errorMessage) {\n try {\n const transferState = this.activeTransfers.get(errorMessage.fileId);\n if (transferState) {\n transferState.status = 'failed';\n this.cleanupTransfer(errorMessage.fileId);\n }\n \n const receivingState = this.receivingTransfers.get(errorMessage.fileId);\n if (receivingState) {\n receivingState.status = 'failed';\n this.cleanupReceivingTransfer(errorMessage.fileId);\n }\n \n if (this.onError) {\n this.onError(`Transfer error: ${errorMessage.error || 'Unknown error'}`);\n }\n \n } catch (error) {\n console.error('\u274C Failed to handle transfer error:', error);\n }\n }\n\n // ============================================\n // UTILITY METHODS\n // ============================================\n\n getActiveTransfers() {\n return Array.from(this.activeTransfers.values()).map(transfer => ({\n fileId: transfer.fileId,\n fileName: transfer.file?.name || 'Unknown',\n fileSize: transfer.file?.size || 0,\n progress: Math.round((transfer.sentChunks / transfer.totalChunks) * 100),\n status: transfer.status,\n startTime: transfer.startTime\n }));\n }\n\n getReceivingTransfers() {\n return Array.from(this.receivingTransfers.values()).map(transfer => ({\n fileId: transfer.fileId,\n fileName: transfer.fileName || 'Unknown',\n fileSize: transfer.fileSize || 0,\n progress: Math.round((transfer.receivedCount / transfer.totalChunks) * 100),\n status: transfer.status,\n startTime: transfer.startTime\n }));\n }\n\n cancelTransfer(fileId) {\n try {\n if (this.activeTransfers.has(fileId)) {\n this.cleanupTransfer(fileId);\n return true;\n }\n if (this.receivingTransfers.has(fileId)) {\n this.cleanupReceivingTransfer(fileId);\n return true;\n }\n return false;\n } catch (error) {\n console.error('\u274C Failed to cancel transfer:', error);\n return false;\n }\n }\n\n cleanupTransfer(fileId) {\n this.activeTransfers.delete(fileId);\n this.sessionKeys.delete(fileId);\n this.transferNonces.delete(fileId);\n \n // Remove processed chunk IDs for this transfer\n for (const chunkId of this.processedChunks) {\n if (chunkId.startsWith(fileId)) {\n this.processedChunks.delete(chunkId);\n }\n }\n }\n\n // \u2705 \u0423\u041B\u0423\u0427\u0428\u0415\u041D\u041D\u0410\u042F \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u0430\u044F \u043E\u0447\u0438\u0441\u0442\u043A\u0430 \u043F\u0430\u043C\u044F\u0442\u0438 \u0434\u043B\u044F \u043F\u0440\u0435\u0434\u043E\u0442\u0432\u0440\u0430\u0449\u0435\u043D\u0438\u044F use-after-free\n cleanupReceivingTransfer(fileId) {\n try {\n // \u0411\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E \u043E\u0447\u0438\u0449\u0430\u0435\u043C pending chunks\n this.pendingChunks.delete(fileId);\n \n const receivingState = this.receivingTransfers.get(fileId);\n if (receivingState) {\n // \u2705 \u0411\u0415\u0417\u041E\u041F\u0410\u0421\u041D\u0410\u042F \u043E\u0447\u0438\u0441\u0442\u043A\u0430 receivedChunks \u0441 \u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0439 \u0437\u0430\u0449\u0438\u0442\u043E\u0439\n if (receivingState.receivedChunks && receivingState.receivedChunks.size > 0) {\n for (const [index, chunk] of receivingState.receivedChunks) {\n try {\n // \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043D\u0430 \u0432\u0430\u043B\u0438\u0434\u043D\u043E\u0441\u0442\u044C chunk\n if (chunk && (chunk instanceof ArrayBuffer || chunk instanceof Uint8Array)) {\n SecureMemoryManager.secureWipe(chunk);\n \n // \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u043E\u0447\u0438\u0441\u0442\u043A\u0430 - \u0437\u0430\u043F\u043E\u043B\u043D\u044F\u0435\u043C \u043D\u0443\u043B\u044F\u043C\u0438 \u043F\u0435\u0440\u0435\u0434 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u0435\u043C\n if (chunk instanceof ArrayBuffer) {\n const view = new Uint8Array(chunk);\n view.fill(0);\n } else if (chunk instanceof Uint8Array) {\n chunk.fill(0);\n }\n }\n } catch (chunkError) {\n console.warn('\u26A0\uFE0F Failed to securely wipe chunk:', chunkError);\n }\n }\n receivingState.receivedChunks.clear();\n }\n \n // \u2705 \u0411\u0415\u0417\u041E\u041F\u0410\u0421\u041D\u0410\u042F \u043E\u0447\u0438\u0441\u0442\u043A\u0430 session key\n if (receivingState.sessionKey) {\n try {\n // \u0414\u043B\u044F CryptoKey \u043D\u0435\u043B\u044C\u0437\u044F \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E \u043E\u0447\u0438\u0441\u0442\u0438\u0442\u044C, \u043D\u043E \u043C\u043E\u0436\u0435\u043C \u0443\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0441\u044B\u043B\u043A\u0443\n receivingState.sessionKey = null;\n } catch (keyError) {\n console.warn('\u26A0\uFE0F Failed to clear session key:', keyError);\n }\n }\n \n // \u2705 \u0411\u0415\u0417\u041E\u041F\u0410\u0421\u041D\u0410\u042F \u043E\u0447\u0438\u0441\u0442\u043A\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0445 \u0434\u0430\u043D\u043D\u044B\u0445\n if (receivingState.salt) {\n try {\n if (Array.isArray(receivingState.salt)) {\n receivingState.salt.fill(0);\n }\n receivingState.salt = null;\n } catch (saltError) {\n console.warn('\u26A0\uFE0F Failed to clear salt:', saltError);\n }\n }\n \n // \u041E\u0447\u0438\u0449\u0430\u0435\u043C \u0432\u0441\u0435 \u0441\u0432\u043E\u0439\u0441\u0442\u0432\u0430 receivingState\n for (const [key, value] of Object.entries(receivingState)) {\n if (value && typeof value === 'object') {\n if (value instanceof ArrayBuffer || value instanceof Uint8Array) {\n SecureMemoryManager.secureWipe(value);\n } else if (Array.isArray(value)) {\n value.fill(0);\n }\n receivingState[key] = null;\n }\n }\n }\n \n // \u0423\u0434\u0430\u043B\u044F\u0435\u043C \u0438\u0437 \u043E\u0441\u043D\u043E\u0432\u043D\u044B\u0445 \u043A\u043E\u043B\u043B\u0435\u043A\u0446\u0438\u0439\n this.receivingTransfers.delete(fileId);\n this.sessionKeys.delete(fileId);\n \n // \u2705 \u0411\u0415\u0417\u041E\u041F\u0410\u0421\u041D\u0410\u042F \u043E\u0447\u0438\u0441\u0442\u043A\u0430 \u0444\u0438\u043D\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u0431\u0443\u0444\u0435\u0440\u0430 \u0444\u0430\u0439\u043B\u0430\n const fileBuffer = this.receivedFileBuffers.get(fileId);\n if (fileBuffer) {\n try {\n if (fileBuffer.buffer) {\n SecureMemoryManager.secureWipe(fileBuffer.buffer);\n \n // \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u043E\u0447\u0438\u0441\u0442\u043A\u0430 - \u0437\u0430\u043F\u043E\u043B\u043D\u044F\u0435\u043C \u043D\u0443\u043B\u044F\u043C\u0438\n const view = new Uint8Array(fileBuffer.buffer);\n view.fill(0);\n }\n \n // \u041E\u0447\u0438\u0449\u0430\u0435\u043C \u0432\u0441\u0435 \u0441\u0432\u043E\u0439\u0441\u0442\u0432\u0430 fileBuffer\n for (const [key, value] of Object.entries(fileBuffer)) {\n if (value && typeof value === 'object') {\n if (value instanceof ArrayBuffer || value instanceof Uint8Array) {\n SecureMemoryManager.secureWipe(value);\n }\n fileBuffer[key] = null;\n }\n }\n \n this.receivedFileBuffers.delete(fileId);\n } catch (bufferError) {\n console.warn('\u26A0\uFE0F Failed to securely clear file buffer:', bufferError);\n // \u041F\u0440\u0438\u043D\u0443\u0434\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u0443\u0434\u0430\u043B\u044F\u0435\u043C \u0434\u0430\u0436\u0435 \u043F\u0440\u0438 \u043E\u0448\u0438\u0431\u043A\u0435\n this.receivedFileBuffers.delete(fileId);\n }\n }\n \n // \u2705 \u0411\u0415\u0417\u041E\u041F\u0410\u0421\u041D\u0410\u042F \u043E\u0447\u0438\u0441\u0442\u043A\u0430 processed chunks\n const chunksToRemove = [];\n for (const chunkId of this.processedChunks) {\n if (chunkId.startsWith(fileId)) {\n chunksToRemove.push(chunkId);\n }\n }\n \n // \u0423\u0434\u0430\u043B\u044F\u0435\u043C \u0432 \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u043E\u043C \u0446\u0438\u043A\u043B\u0435 \u0434\u043B\u044F \u0438\u0437\u0431\u0435\u0436\u0430\u043D\u0438\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u043A\u043E\u043B\u043B\u0435\u043A\u0446\u0438\u0438 \u0432\u043E \u0432\u0440\u0435\u043C\u044F \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438\n for (const chunkId of chunksToRemove) {\n this.processedChunks.delete(chunkId);\n }\n \n // \u041F\u0440\u0438\u043D\u0443\u0434\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u043E\u0447\u0438\u0441\u0442\u043A\u0430 \u043F\u0430\u043C\u044F\u0442\u0438\n if (typeof global !== 'undefined' && global.gc) {\n try {\n global.gc();\n } catch (gcError) {\n // \u0418\u0433\u043D\u043E\u0440\u0438\u0440\u0443\u0435\u043C \u043E\u0448\u0438\u0431\u043A\u0438 GC\n }\n }\n \n console.log(`\uD83D\uDD12 Memory safely cleaned for file transfer: ${fileId}`);\n \n } catch (error) {\n console.error('\u274C Error during secure memory cleanup:', error);\n \n // \u041F\u0440\u0438\u043D\u0443\u0434\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u043E\u0447\u0438\u0441\u0442\u043A\u0430 \u0434\u0430\u0436\u0435 \u043F\u0440\u0438 \u043E\u0448\u0438\u0431\u043A\u0435\n this.receivingTransfers.delete(fileId);\n this.sessionKeys.delete(fileId);\n this.receivedFileBuffers.delete(fileId);\n this.pendingChunks.delete(fileId);\n \n throw new Error(`Memory cleanup failed: ${error.message}`);\n }\n }\n\n getTransferStatus(fileId) {\n if (this.activeTransfers.has(fileId)) {\n const transfer = this.activeTransfers.get(fileId);\n return {\n type: 'sending',\n fileId: transfer.fileId,\n fileName: transfer.file.name,\n progress: Math.round((transfer.sentChunks / transfer.totalChunks) * 100),\n status: transfer.status,\n startTime: transfer.startTime\n };\n }\n \n if (this.receivingTransfers.has(fileId)) {\n const transfer = this.receivingTransfers.get(fileId);\n return {\n type: 'receiving',\n fileId: transfer.fileId,\n fileName: transfer.fileName,\n progress: Math.round((transfer.receivedCount / transfer.totalChunks) * 100),\n status: transfer.status,\n startTime: transfer.startTime\n };\n }\n \n return null;\n }\n\n getSystemStatus() {\n return {\n initialized: true,\n activeTransfers: this.activeTransfers.size,\n receivingTransfers: this.receivingTransfers.size,\n totalTransfers: this.activeTransfers.size + this.receivingTransfers.size,\n maxConcurrentTransfers: this.MAX_CONCURRENT_TRANSFERS,\n maxFileSize: this.MAX_FILE_SIZE,\n chunkSize: this.CHUNK_SIZE,\n hasWebrtcManager: !!this.webrtcManager,\n isConnected: this.webrtcManager?.isConnected?.() || false,\n hasDataChannel: !!this.webrtcManager?.dataChannel,\n dataChannelState: this.webrtcManager?.dataChannel?.readyState,\n isVerified: this.webrtcManager?.isVerified,\n hasEncryptionKey: !!this.webrtcManager?.encryptionKey,\n hasMacKey: !!this.webrtcManager?.macKey,\n linkedToWebRTCManager: this.webrtcManager?.fileTransferSystem === this,\n supportedFileTypes: this.getSupportedFileTypes(),\n fileTypeInfo: this.getFileTypeInfo()\n };\n }\n\n cleanup() {\n SecureFileTransferContext.getInstance().deactivate();\n\n if (this.webrtcManager && this.webrtcManager.dataChannel && this.originalOnMessage) {\n this.webrtcManager.dataChannel.onmessage = this.originalOnMessage;\n this.originalOnMessage = null;\n }\n \n if (this.webrtcManager && this.originalProcessMessage) {\n this.webrtcManager.processMessage = this.originalProcessMessage;\n this.originalProcessMessage = null;\n }\n \n if (this.webrtcManager && this.originalRemoveSecurityLayers) {\n this.webrtcManager.removeSecurityLayers = this.originalRemoveSecurityLayers;\n this.originalRemoveSecurityLayers = null;\n }\n \n // Cleanup all active transfers with secure memory wiping\n for (const fileId of this.activeTransfers.keys()) {\n this.cleanupTransfer(fileId);\n }\n \n for (const fileId of this.receivingTransfers.keys()) {\n this.cleanupReceivingTransfer(fileId);\n }\n\n if (this.atomicOps) {\n this.atomicOps.locks.clear();\n }\n \n if (this.rateLimiter) {\n this.rateLimiter.requests.clear();\n }\n \n // Clear all state\n this.pendingChunks.clear();\n this.activeTransfers.clear();\n this.receivingTransfers.clear();\n this.transferQueue.length = 0;\n this.sessionKeys.clear();\n this.transferNonces.clear();\n this.processedChunks.clear();\n\n this.clearKeys();\n }\n\n // ============================================\n // SESSION UPDATE HANDLER - FIXED\n // ============================================\n \n onSessionUpdate(sessionData) {\n // Clear session keys cache for resync\n this.sessionKeys.clear();\n }\n\n // ============================================\n // DEBUGGING AND DIAGNOSTICS\n // ============================================\n\n diagnoseFileTransferIssue() {\n const diagnosis = {\n timestamp: new Date().toISOString(),\n fileTransferSystem: {\n initialized: !!this,\n hasWebrtcManager: !!this.webrtcManager,\n webrtcManagerType: this.webrtcManager?.constructor?.name,\n linkedToWebRTCManager: this.webrtcManager?.fileTransferSystem === this\n },\n webrtcManager: {\n hasDataChannel: !!this.webrtcManager?.dataChannel,\n dataChannelState: this.webrtcManager?.dataChannel?.readyState,\n isConnected: this.webrtcManager?.isConnected?.() || false,\n isVerified: this.webrtcManager?.isVerified,\n hasEncryptionKey: !!this.webrtcManager?.encryptionKey,\n hasMacKey: !!this.webrtcManager?.macKey,\n hasKeyFingerprint: !!this.webrtcManager?.keyFingerprint,\n hasSessionSalt: !!this.webrtcManager?.sessionSalt\n },\n securityContext: {\n contextActive: SecureFileTransferContext.getInstance().isActive(),\n securityLevel: SecureFileTransferContext.getInstance().getSecurityLevel(),\n hasAtomicOps: !!this.atomicOps,\n hasRateLimiter: !!this.rateLimiter\n },\n transfers: {\n activeTransfers: this.activeTransfers.size,\n receivingTransfers: this.receivingTransfers.size,\n pendingChunks: this.pendingChunks.size,\n sessionKeys: this.sessionKeys.size\n },\n fileTypeSupport: {\n supportedTypes: this.getSupportedFileTypes(),\n generalMaxSize: this.formatFileSize(this.MAX_FILE_SIZE),\n restrictions: Object.keys(this.FILE_TYPE_RESTRICTIONS)\n }\n };\n \n return diagnosis;\n }\n\n async debugKeyDerivation(fileId) {\n try {\n if (!this.webrtcManager.keyFingerprint || !this.webrtcManager.sessionSalt) {\n throw new Error('Session data not available');\n }\n \n // Test sender derivation\n const senderResult = await this.deriveFileSessionKey(fileId);\n \n // Test receiver derivation with same salt\n const receiverKey = await this.deriveFileSessionKeyFromSalt(fileId, senderResult.salt);\n \n // Test encryption/decryption\n const testData = new TextEncoder().encode('test data');\n const nonce = crypto.getRandomValues(new Uint8Array(12));\n \n const encrypted = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: nonce },\n senderResult.key,\n testData\n );\n \n const decrypted = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: nonce },\n receiverKey,\n encrypted\n );\n \n const decryptedText = new TextDecoder().decode(decrypted);\n \n if (decryptedText === 'test data') {\n return { success: true, message: 'All tests passed' };\n } else {\n throw new Error('Decryption verification failed');\n }\n \n } catch (error) {\n console.error('\u274C Key derivation test failed:', error);\n return { success: false, error: error.message };\n }\n }\n\n // ============================================\n // ALTERNATIVE METHOD OF INITIALIZING HANDLERS\n // ============================================\n\n registerWithWebRTCManager() {\n if (!this.webrtcManager) {\n throw new Error('WebRTC manager not available');\n }\n\n this.webrtcManager.fileTransferSystem = this;\n\n this.webrtcManager.setFileMessageHandler = (handler) => {\n this.webrtcManager._fileMessageHandler = handler;\n };\n\n this.webrtcManager.setFileMessageHandler((message) => {\n return this.handleFileMessage(message);\n });\n }\n\n static createFileMessageFilter(fileTransferSystem) {\n return async (event) => {\n try {\n if (typeof event.data === 'string') {\n const parsed = JSON.parse(event.data);\n \n if (fileTransferSystem.isFileTransferMessage(parsed)) {\n await fileTransferSystem.handleFileMessage(parsed);\n return true; \n }\n }\n } catch (error) {\n }\n \n return false; \n };\n }\n\n // ============================================\n // SECURITY KEY MANAGEMENT\n // ============================================\n\n setSigningKey(privateKey) {\n if (!privateKey || !(privateKey instanceof CryptoKey)) {\n throw new Error('Invalid private key for signing');\n }\n this.signingKey = privateKey;\n console.log('\uD83D\uDD12 Signing key set successfully');\n }\n\n setVerificationKey(publicKey) {\n if (!publicKey || !(publicKey instanceof CryptoKey)) {\n throw new Error('Invalid public key for verification');\n }\n this.verificationKey = publicKey;\n console.log('\uD83D\uDD12 Verification key set successfully');\n }\n\n async generateSigningKeyPair() {\n try {\n const keyPair = await crypto.subtle.generateKey(\n {\n name: 'RSASSA-PKCS1-v1_5',\n modulusLength: 2048,\n publicExponent: new Uint8Array([1, 0, 1]),\n hash: 'SHA-256'\n },\n true, // extractable\n ['sign', 'verify']\n );\n \n this.signingKey = keyPair.privateKey;\n this.verificationKey = keyPair.publicKey;\n \n console.log('\uD83D\uDD12 RSA key pair generated successfully');\n return keyPair;\n } catch (error) {\n const safeError = SecurityErrorHandler.sanitizeError(error);\n console.error('\u274C Failed to generate signing key pair:', safeError);\n throw new Error(safeError);\n }\n }\n\n clearKeys() {\n this.signingKey = null;\n this.verificationKey = null;\n console.log('\uD83D\uDD12 Security keys cleared');\n }\n\n getSecurityStatus() {\n return {\n signingEnabled: this.signingKey !== null,\n verificationEnabled: this.verificationKey !== null,\n contextActive: SecureFileTransferContext.getInstance().isActive(),\n securityLevel: SecureFileTransferContext.getInstance().getSecurityLevel()\n };\n }\n\n getClientIdentifier() {\n return this.webrtcManager?.connectionId || \n this.webrtcManager?.keyFingerprint?.substring(0, 16) || \n 'default-client';\n }\n \n destroy() {\n SecureFileTransferContext.getInstance().deactivate();\n this.clearKeys();\n console.log('\uD83D\uDD12 File transfer system destroyed safely');\n }\n}\n\nexport { EnhancedSecureFileTransfer };", "// Import EnhancedSecureFileTransfer\nimport { EnhancedSecureFileTransfer } from '../transfer/EnhancedSecureFileTransfer.js';\n\n// MUTEX SYSTEM FIXES - RESOLVING MESSAGE DELIVERY ISSUES\n// ============================================\n// Issue: After introducing the Mutex system, messages stopped being delivered between users\n// Fix: Simplified locking logic \u2014 mutex is used ONLY for critical operations\n// - Regular messages are processed WITHOUT mutex\n// - File messages are processed WITHOUT mutex \n// - Mutex is used ONLY for cryptographic operations\n// ============================================\n\nclass EnhancedSecureWebRTCManager {\n // ============================================\n // CONSTANTS\n // ============================================\n \n static TIMEOUTS = {\n KEY_ROTATION_INTERVAL: 300000, // 5 minutes\n CONNECTION_TIMEOUT: 10000, // 10 seconds \n HEARTBEAT_INTERVAL: 30000, // 30 seconds\n SECURITY_CALC_DELAY: 1000, // 1 second\n SECURITY_CALC_RETRY_DELAY: 3000, // 3 seconds\n CLEANUP_INTERVAL: 300000, // 5 minutes (periodic cleanup)\n CLEANUP_CHECK_INTERVAL: 60000, // 1 minute (cleanup check)\n ICE_GATHERING_TIMEOUT: 10000, // 10 seconds\n DISCONNECT_CLEANUP_DELAY: 500, // 500ms\n PEER_DISCONNECT_CLEANUP: 2000, // 2 seconds\n STAGE2_ACTIVATION_DELAY: 10000, // 10 seconds\n STAGE3_ACTIVATION_DELAY: 15000, // 15 seconds \n STAGE4_ACTIVATION_DELAY: 20000, // 20 seconds\n FILE_TRANSFER_INIT_DELAY: 1000, // 1 second\n FAKE_TRAFFIC_MIN_INTERVAL: 15000, // 15 seconds\n FAKE_TRAFFIC_MAX_INTERVAL: 30000, // 30 seconds\n DECOY_INITIAL_DELAY: 5000, // 5 seconds\n DECOY_TRAFFIC_MIN: 10000, // 10 seconds\n DECOY_TRAFFIC_MAX: 25000, // 25 seconds\n REORDER_TIMEOUT: 3000, // 3 seconds\n RETRY_CONNECTION_DELAY: 2000 // 2 seconds\n };\n\n static LIMITS = {\n MAX_CONNECTION_ATTEMPTS: 3,\n MAX_OLD_KEYS: 3,\n MAX_PROCESSED_MESSAGE_IDS: 1000,\n MAX_OUT_OF_ORDER_PACKETS: 5,\n MAX_DECOY_CHANNELS: 1,\n MESSAGE_RATE_LIMIT: 60, // messages per minute\n MAX_KEY_AGE: 900000, // 15 minutes\n OFFER_MAX_AGE: 3600000, // 1 hour\n SALT_SIZE_V3: 32, // bytes\n SALT_SIZE_V4: 64 // bytes\n };\n\n static SIZES = {\n VERIFICATION_CODE_MIN_LENGTH: 6,\n FAKE_TRAFFIC_MIN_SIZE: 32,\n FAKE_TRAFFIC_MAX_SIZE: 128,\n PACKET_PADDING_MIN: 64,\n PACKET_PADDING_MAX: 512,\n CHUNK_SIZE_MAX: 2048,\n CHUNK_DELAY_MIN: 100,\n CHUNK_DELAY_MAX: 500,\n FINGERPRINT_DISPLAY_LENGTH: 8,\n SESSION_ID_LENGTH: 16,\n NESTED_ENCRYPTION_IV_SIZE: 12\n };\n\n static MESSAGE_TYPES = {\n // Regular messages\n MESSAGE: 'message',\n ENHANCED_MESSAGE: 'enhanced_message',\n \n // System messages\n HEARTBEAT: 'heartbeat',\n VERIFICATION: 'verification',\n VERIFICATION_RESPONSE: 'verification_response',\n VERIFICATION_CONFIRMED: 'verification_confirmed',\n VERIFICATION_BOTH_CONFIRMED: 'verification_both_confirmed',\n PEER_DISCONNECT: 'peer_disconnect',\n SECURITY_UPGRADE: 'security_upgrade',\n KEY_ROTATION_SIGNAL: 'key_rotation_signal',\n KEY_ROTATION_READY: 'key_rotation_ready',\n \n // File transfer messages\n FILE_TRANSFER_START: 'file_transfer_start',\n FILE_TRANSFER_RESPONSE: 'file_transfer_response',\n FILE_CHUNK: 'file_chunk',\n CHUNK_CONFIRMATION: 'chunk_confirmation',\n FILE_TRANSFER_COMPLETE: 'file_transfer_complete',\n FILE_TRANSFER_ERROR: 'file_transfer_error',\n \n // Fake traffic\n FAKE: 'fake'\n };\n\n static FILTERED_RESULTS = {\n FAKE_MESSAGE: 'FAKE_MESSAGE_FILTERED',\n FILE_MESSAGE: 'FILE_MESSAGE_FILTERED', \n SYSTEM_MESSAGE: 'SYSTEM_MESSAGE_FILTERED'\n };\n\n // Static debug flag instead of this._debugMode\n static DEBUG_MODE = false; // Set to true during development, false in production\n\n\n constructor(onMessage, onStatusChange, onKeyExchange, onVerificationRequired, onAnswerError = null, onVerificationStateChange = null, config = {}) {\n // Determine runtime mode\n this._isProductionMode = this._detectProductionMode();\n // Use static flag instead of this._debugMode\n this._debugMode = !this._isProductionMode && EnhancedSecureWebRTCManager.DEBUG_MODE;\n \n // Configuration from constructor parameters instead of global flags\n this._config = {\n fakeTraffic: {\n enabled: config.fakeTraffic?.enabled ?? true,\n minInterval: config.fakeTraffic?.minInterval ?? EnhancedSecureWebRTCManager.TIMEOUTS.FAKE_TRAFFIC_MIN_INTERVAL,\n maxInterval: config.fakeTraffic?.maxInterval ?? EnhancedSecureWebRTCManager.TIMEOUTS.FAKE_TRAFFIC_MAX_INTERVAL,\n minSize: config.fakeTraffic?.minSize ?? EnhancedSecureWebRTCManager.SIZES.FAKE_TRAFFIC_MIN_SIZE,\n maxSize: config.fakeTraffic?.maxSize ?? EnhancedSecureWebRTCManager.SIZES.FAKE_TRAFFIC_MAX_SIZE,\n patterns: config.fakeTraffic?.patterns ?? ['heartbeat', 'status', 'sync']\n },\n decoyChannels: {\n enabled: config.decoyChannels?.enabled ?? true,\n maxDecoyChannels: config.decoyChannels?.maxDecoyChannels ?? EnhancedSecureWebRTCManager.LIMITS.MAX_DECOY_CHANNELS,\n decoyChannelNames: config.decoyChannels?.decoyChannelNames ?? ['heartbeat'],\n sendDecoyData: config.decoyChannels?.sendDecoyData ?? true,\n randomDecoyIntervals: config.decoyChannels?.randomDecoyIntervals ?? true\n },\n packetPadding: {\n enabled: config.packetPadding?.enabled ?? true,\n minPadding: config.packetPadding?.minPadding ?? EnhancedSecureWebRTCManager.SIZES.PACKET_PADDING_MIN,\n maxPadding: config.packetPadding?.maxPadding ?? EnhancedSecureWebRTCManager.SIZES.PACKET_PADDING_MAX,\n useRandomPadding: config.packetPadding?.useRandomPadding ?? true,\n preserveMessageSize: config.packetPadding?.preserveMessageSize ?? false\n },\n antiFingerprinting: {\n enabled: config.antiFingerprinting?.enabled ?? false,\n randomizeTiming: config.antiFingerprinting?.randomizeTiming ?? true,\n randomizeSizes: config.antiFingerprinting?.randomizeSizes ?? false,\n addNoise: config.antiFingerprinting?.addNoise ?? true,\n maskPatterns: config.antiFingerprinting?.maskPatterns ?? false,\n useRandomHeaders: config.antiFingerprinting?.useRandomHeaders ?? false\n }\n };\n\n // Initialize own logging system\n this._initializeSecureLogging();\n this._setupOwnLogger();\n this._setupProductionLogging();\n \n // Store important methods first\n this._storeImportantMethods();\n \n // Setup global API after storing methods\n this._setupSecureGlobalAPI();\n if (!window.EnhancedSecureCryptoUtils) {\n throw new Error('EnhancedSecureCryptoUtils is not loaded. Please ensure the module is loaded first.');\n }\n this.getSecurityData = () => {\n // Return only public information\n return this.lastSecurityCalculation ? {\n level: this.lastSecurityCalculation.level,\n score: this.lastSecurityCalculation.score,\n timestamp: this.lastSecurityCalculation.timestamp,\n // Do NOT return check details or sensitive data\n } : null;\n };\n this._secureLog('info', '\uD83D\uDD12 Enhanced WebRTC Manager initialized with secure API');\n this.currentSessionType = null;\n this.currentSecurityLevel = 'basic';\n this.sessionConstraints = null;\n this.peerConnection = null;\n this.dataChannel = null;\n\n\n this.onMessage = onMessage;\n this.onStatusChange = onStatusChange;\n this.onKeyExchange = onKeyExchange;\n this.onVerificationStateChange = onVerificationStateChange;\n\n this.onVerificationRequired = onVerificationRequired;\n this.onAnswerError = onAnswerError; // Callback for response processing errors\n this.isInitiator = false;\n this.connectionAttempts = 0;\n this.maxConnectionAttempts = EnhancedSecureWebRTCManager.LIMITS.MAX_CONNECTION_ATTEMPTS;\n try {\n this._initializeMutexSystem();\n} catch (error) {\n this._secureLog('error', '\u274C Failed to initialize mutex system', {\n errorType: error.constructor.name\n });\n throw new Error('Critical: Mutex system initialization failed');\n}\n\n// Post-initialization validation of the mutex system\nif (!this._validateMutexSystem()) {\n this._secureLog('error', '\u274C Mutex system validation failed after initialization');\n throw new Error('Critical: Mutex system validation failed');\n}\n\nif (typeof window !== 'undefined') {\n this._secureLog('info', '\uD83D\uDD12 Emergency mutex handlers will be available through secure API');\n}\n\nthis._secureLog('info', '\uD83D\uDD12 Enhanced Mutex system fully initialized and validated');\n this.heartbeatInterval = null;\n this.messageQueue = [];\n this.ecdhKeyPair = null;\n this.ecdsaKeyPair = null;\n if (this.fileTransferSystem) {\n this.fileTransferSystem.cleanup();\n this.fileTransferSystem = null;\n }\n this.verificationCode = null;\n this.pendingSASCode = null;\n this.isVerified = false;\n this.processedMessageIds = new Set();\n \n // Mutual verification states\n this.localVerificationConfirmed = false;\n this.remoteVerificationConfirmed = false;\n this.bothVerificationsConfirmed = false;\n \n // Store expected DTLS fingerprint for validation\n this.expectedDTLSFingerprint = null;\n this.strictDTLSValidation = true; // Can be disabled for debugging\n \n // Real Perfect Forward Secrecy implementation\n this.ephemeralKeyPairs = new Map(); // Store ephemeral keys for current session only\n this.sessionStartTime = Date.now(); // Track session lifetime for PFS\n this.messageCounter = 0;\n this.sequenceNumber = 0;\n this.expectedSequenceNumber = 0;\n this.sessionSalt = null;\n \n // Anti-Replay and Message Ordering Protection\n this.replayWindowSize = 64; // Sliding window for replay protection\n this.replayWindow = new Set(); // Track recent sequence numbers\n this.maxSequenceGap = 100; // Maximum allowed sequence gap\n this.replayProtectionEnabled = true; // Enable/disable replay protection\n this.sessionId = null; // MITM protection: Session identifier\n this.connectionId = Array.from(crypto.getRandomValues(new Uint8Array(8)))\n .map(b => b.toString(16).padStart(2, '0')).join(''); // Connection identifier for AAD\n this.peerPublicKey = null; // Store peer's public key for PFS\n this.rateLimiterId = null;\n this.intentionalDisconnect = false;\n this.lastCleanupTime = Date.now();\n \n // Reset notification flags for new connection\n this._resetNotificationFlags();\n \n \n\n this.verificationInitiationSent = false;\n this.disconnectNotificationSent = false;\n this.reconnectionFailedNotificationSent = false;\n this.peerDisconnectNotificationSent = false;\n this.connectionClosedNotificationSent = false;\n this.fakeTrafficDisabledNotificationSent = false;\n this.advancedFeaturesDisabledNotificationSent = false;\n this.securityUpgradeNotificationSent = false;\n this.lastSecurityUpgradeStage = null;\n this.securityCalculationNotificationSent = false;\n this.lastSecurityCalculationLevel = null;\n \n // File transfer integration\n this.fileTransferSystem = null;\n this.onFileProgress = null;\n \n // ============================================\n // IV REUSE PREVENTION SYSTEM\n // ============================================\n // IV REUSE PREVENTION SYSTEM WITH LIMITS\n // ============================================\n this._ivTrackingSystem = {\n usedIVs: new Set(), // Track all used IVs to prevent reuse\n ivHistory: new Map(), // Track IV usage with timestamps (max 10k entries)\n collisionCount: 0, // Track potential collisions\n maxIVHistorySize: 10000, // Maximum IV history size\n maxSessionIVs: 1000, // Maximum IVs per session\n entropyValidation: {\n minEntropy: 3.0, // Minimum entropy threshold\n entropyTests: 0,\n entropyFailures: 0\n },\n rngValidation: {\n testsPerformed: 0,\n weakRngDetected: false,\n lastValidation: 0\n },\n sessionIVs: new Map(), // Track IVs per session\n emergencyMode: false // Emergency mode if IV reuse detected\n };\n \n // IV cleanup tracking\n this._lastIVCleanupTime = null;\n \n // ============================================\n // SECURE ERROR HANDLING SYSTEM\n // ============================================\n this._secureErrorHandler = {\n errorCategories: {\n CRYPTOGRAPHIC: 'cryptographic',\n NETWORK: 'network',\n VALIDATION: 'validation',\n SYSTEM: 'system',\n UNKNOWN: 'unknown'\n },\n errorMappings: new Map(), // Map internal errors to safe messages\n errorCounts: new Map(), // Track error frequencies\n lastErrorTime: 0,\n errorThreshold: 10, // Max errors per minute\n isInErrorMode: false\n };\n \n // ============================================\n // SECURE MEMORY MANAGEMENT SYSTEM\n // ============================================\n this._secureMemoryManager = {\n sensitiveData: new WeakMap(), // Track sensitive data for secure cleanup\n cleanupQueue: [], // Queue for deferred cleanup operations\n isCleaning: false, // Prevent concurrent cleanup operations\n cleanupInterval: null, // Periodic cleanup timer\n memoryStats: {\n totalCleanups: 0,\n failedCleanups: 0,\n lastCleanup: 0\n }\n };\n this.onFileReceived = null;\n this.onFileError = null;\n \n // PFS (Perfect Forward Secrecy) Implementation\n this.keyRotationInterval = EnhancedSecureWebRTCManager.TIMEOUTS.KEY_ROTATION_INTERVAL;\n this.lastKeyRotation = Date.now();\n this.currentKeyVersion = 0;\n this.keyVersions = new Map(); // Store key versions for PFS\n this.oldKeys = new Map(); // Store old keys temporarily for decryption\n this.maxOldKeys = EnhancedSecureWebRTCManager.LIMITS.MAX_OLD_KEYS; // Keep last 3 key versions for decryption\n this.peerConnection = null;\n this.dataChannel = null;\n \n\n this.securityFeatures = {\n\n hasEncryption: true, \n hasECDH: true, \n hasECDSA: false, \n hasMutualAuth: false, \n hasMetadataProtection: false, \n hasEnhancedReplayProtection: false, \n hasNonExtractableKeys: false, \n hasRateLimiting: true, \n hasEnhancedValidation: false, \n hasPFS: true, // Real Perfect Forward Secrecy enabled \n \n // Advanced Features (Session Managed) \n hasNestedEncryption: false, \n hasPacketPadding: false, \n hasPacketReordering: false, \n hasAntiFingerprinting: false, \n hasFakeTraffic: false, \n hasDecoyChannels: false, \n hasMessageChunking: false \n };\n this._secureLog('info', '\uD83D\uDD12 Enhanced WebRTC Manager initialized with tiered security');\n \n // Log configuration for debugging\n this._secureLog('info', '\uD83D\uDD12 Configuration loaded from constructor parameters', {\n fakeTraffic: this._config.fakeTraffic.enabled,\n decoyChannels: this._config.decoyChannels.enabled,\n packetPadding: this._config.packetPadding.enabled,\n antiFingerprinting: this._config.antiFingerprinting.enabled\n });\n \n // XSS Hardening - replace all window.DEBUG_MODE references\n this._hardenDebugModeReferences();\n \n // Initialize unified scheduler for all maintenance tasks\n this._initializeUnifiedScheduler();\n \n this._syncSecurityFeaturesWithTariff();\n \n if (!this._validateCryptographicSecurity()) {\n this._secureLog('error', '\uD83D\uDEA8 CRITICAL: Cryptographic security validation failed after tariff sync');\n throw new Error('Critical cryptographic features are missing after tariff synchronization');\n }\n // ============================================\n // ENHANCED SECURITY FEATURES\n // ============================================\n \n // 1. Nested Encryption Layer\n this.nestedEncryptionKey = null;\n // Removed nestedEncryptionIV and nestedEncryptionCounter\n // Each nested encryption now generates fresh random IV for maximum security\n \n // 2. Packet Padding\n this.paddingConfig = {\n enabled: this._config.packetPadding.enabled,\n minPadding: this._config.packetPadding.minPadding,\n maxPadding: this._config.packetPadding.maxPadding,\n useRandomPadding: this._config.packetPadding.useRandomPadding,\n preserveMessageSize: this._config.packetPadding.preserveMessageSize\n };\n \n // 3. Fake Traffic Generation\n this.fakeTrafficConfig = {\n enabled: this._config.fakeTraffic.enabled,\n minInterval: this._config.fakeTraffic.minInterval,\n maxInterval: this._config.fakeTraffic.maxInterval,\n minSize: this._config.fakeTraffic.minSize,\n maxSize: this._config.fakeTraffic.maxSize,\n patterns: this._config.fakeTraffic.patterns\n };\n this.fakeTrafficTimer = null;\n this.lastFakeTraffic = 0;\n \n // 4. Message Chunking\n this.chunkingConfig = {\n enabled: false,\n maxChunkSize: EnhancedSecureWebRTCManager.SIZES.CHUNK_SIZE_MAX, \n minDelay: EnhancedSecureWebRTCManager.SIZES.CHUNK_DELAY_MIN,\n maxDelay: EnhancedSecureWebRTCManager.SIZES.CHUNK_DELAY_MAX,\n useRandomDelays: true,\n addChunkHeaders: true\n };\n this.chunkQueue = [];\n this.chunkingInProgress = false;\n \n // 5. Decoy Channels\n this.decoyChannels = new Map();\n this.decoyChannelConfig = {\n enabled: this._config.decoyChannels.enabled,\n maxDecoyChannels: this._config.decoyChannels.maxDecoyChannels,\n decoyChannelNames: this._config.decoyChannels.decoyChannelNames,\n sendDecoyData: this._config.decoyChannels.sendDecoyData,\n randomDecoyIntervals: this._config.decoyChannels.randomDecoyIntervals\n };\n this.decoyTimers = new Map();\n \n // 6. Packet Reordering Protection\n this.reorderingConfig = {\n enabled: false, \n maxOutOfOrder: EnhancedSecureWebRTCManager.LIMITS.MAX_OUT_OF_ORDER_PACKETS, \n reorderTimeout: EnhancedSecureWebRTCManager.TIMEOUTS.REORDER_TIMEOUT, \n useSequenceNumbers: true,\n useTimestamps: true\n };\n this.packetBuffer = new Map(); // sequence -> {data, timestamp}\n this.lastProcessedSequence = -1;\n \n // 7. Anti-Fingerprinting\n this.antiFingerprintingConfig = {\n enabled: this._config.antiFingerprinting.enabled,\n randomizeTiming: this._config.antiFingerprinting.randomizeTiming,\n randomizeSizes: this._config.antiFingerprinting.randomizeSizes,\n addNoise: this._config.antiFingerprinting.addNoise,\n maskPatterns: this._config.antiFingerprinting.maskPatterns,\n useRandomHeaders: this._config.antiFingerprinting.useRandomHeaders\n };\n this.fingerprintMask = this.generateFingerprintMask();\n \n // Initialize rate limiter ID\n this.rateLimiterId = `webrtc_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n \n // Start periodic cleanup\n this.startPeriodicCleanup();\n \n this.initializeEnhancedSecurity(); \n \n // ============================================\n // MUTEX SYSTEM TO PREVENT RACE CONDITIONS\n // ============================================\n\n // Mutex for key operations\n this._keyOperationMutex = {\n locked: false,\n queue: [],\n lockId: null,\n lockTimeout: null\n };\n\n // Mutex for encryption/decryption operations\n this._cryptoOperationMutex = {\n locked: false,\n queue: [],\n lockId: null,\n lockTimeout: null\n };\n\n // Mutex for connection initialization\n this._connectionOperationMutex = {\n locked: false,\n queue: [],\n lockId: null,\n lockTimeout: null\n };\n\n // Key system state\n this._keySystemState = {\n isInitializing: false,\n isRotating: false,\n isDestroying: false,\n lastOperation: null,\n lastOperationTime: Date.now()\n };\n\n // Operation counters\n this._operationCounters = {\n keyOperations: 0,\n cryptoOperations: 0,\n connectionOperations: 0\n };\n\n }\n \n /**\n * Create AAD with sequence number for anti-replay protection\n * This binds each message to its sequence number and prevents replay attacks\n */\n _createMessageAAD(messageType, messageData = null, isFileMessage = false) {\n try {\n const aad = {\n sessionId: this.currentSession?.sessionId || this.sessionId || 'unknown',\n keyFingerprint: this.keyFingerprint || 'unknown',\n sequenceNumber: this._generateNextSequenceNumber(),\n messageType: messageType,\n timestamp: Date.now(),\n connectionId: this.connectionId || 'unknown',\n isFileMessage: isFileMessage\n };\n\n // Add message-specific data if available\n if (messageData && typeof messageData === 'object') {\n if (messageData.fileId) aad.fileId = messageData.fileId;\n if (messageData.chunkIndex !== undefined) aad.chunkIndex = messageData.chunkIndex;\n if (messageData.totalChunks !== undefined) aad.totalChunks = messageData.totalChunks;\n }\n\n return JSON.stringify(aad);\n } catch (error) {\n this._secureLog('error', '\u274C Failed to create message AAD', {\n errorType: error.constructor.name,\n message: error.message,\n messageType: messageType\n });\n // Fallback to basic AAD\n return JSON.stringify({\n sessionId: 'unknown',\n keyFingerprint: 'unknown',\n sequenceNumber: Date.now(),\n messageType: messageType,\n timestamp: Date.now(),\n connectionId: 'unknown',\n isFileMessage: isFileMessage\n });\n }\n }\n \n /**\n * Generate next sequence number for outgoing messages\n * This ensures unique ordering and prevents replay attacks\n */\n _generateNextSequenceNumber() {\n const nextSeq = this.sequenceNumber++;\n \n // Reset sequence number if it gets too large\n if (this.sequenceNumber > Number.MAX_SAFE_INTEGER - 1000) {\n this.sequenceNumber = 0;\n this.expectedSequenceNumber = 0;\n this.replayWindow.clear();\n this._secureLog('warn', '\u26A0\uFE0F Sequence number reset due to overflow', {\n timestamp: Date.now()\n });\n }\n \n return nextSeq;\n }\n \n /**\n * Enhanced mutex system initialization with atomic protection\n */\n _initializeMutexSystem() {\n // Initialize standard mutexes with enhanced state tracking\n this._keyOperationMutex = {\n locked: false,\n queue: [],\n lockId: null,\n lockTimeout: null,\n lockTime: null,\n operationCount: 0\n };\n\n this._cryptoOperationMutex = {\n locked: false,\n queue: [],\n lockId: null,\n lockTimeout: null,\n lockTime: null,\n operationCount: 0\n };\n\n this._connectionOperationMutex = {\n locked: false,\n queue: [],\n lockId: null,\n lockTimeout: null,\n lockTime: null,\n operationCount: 0\n };\n\n // Enhanced key system state with atomic operation tracking\n this._keySystemState = {\n isInitializing: false,\n isRotating: false,\n isDestroying: false,\n lastOperation: null,\n lastOperationTime: Date.now(),\n operationId: null,\n concurrentOperations: 0,\n maxConcurrentOperations: 1\n };\n\n // Operation counters with atomic increments\n this._operationCounters = {\n keyOperations: 0,\n cryptoOperations: 0,\n connectionOperations: 0,\n totalOperations: 0,\n failedOperations: 0\n };\n\n this._secureLog('info', '\uD83D\uDD12 Enhanced mutex system initialized with atomic protection', {\n mutexes: ['keyOperation', 'cryptoOperation', 'connectionOperation'],\n timestamp: Date.now(),\n features: ['atomic_operations', 'race_condition_protection', 'enhanced_state_tracking']\n });\n }\n\n /**\n * XSS Hardening - Debug mode references validation\n * This method is called during initialization to ensure XSS hardening\n */\n _hardenDebugModeReferences() {\n // Log that we're hardening debug mode references\n this._secureLog('info', '\uD83D\uDD12 XSS Hardening: Debug mode references already replaced');\n }\n\n /**\n * Unified scheduler for all maintenance tasks\n * Replaces multiple setInterval calls with a single, controlled scheduler\n */\n _initializeUnifiedScheduler() {\n // Single scheduler interval for all maintenance tasks\n this._maintenanceScheduler = setInterval(() => {\n this._executeMaintenanceCycle();\n }, 300000); // Every 5 minutes\n \n // Log scheduler initialization\n this._secureLog('info', '\uD83D\uDD27 Unified maintenance scheduler initialized (5-minute cycle)');\n \n // Store scheduler reference for cleanup\n this._activeTimers = new Set([this._maintenanceScheduler]);\n }\n\n /**\n * Execute all maintenance tasks in a single cycle\n */\n _executeMaintenanceCycle() {\n try {\n this._secureLog('info', '\uD83D\uDD27 Starting maintenance cycle');\n \n // 1. Log cleanup and security audit\n this._cleanupLogs();\n this._auditLoggingSystemSecurity();\n \n // 2. Security monitoring\n this._verifyAPIIntegrity();\n this._validateCryptographicSecurity();\n this._syncSecurityFeaturesWithTariff();\n \n // 3. Resource cleanup\n this._cleanupResources();\n this._enforceResourceLimits();\n \n // 4. Key monitoring (if connected)\n if (this.isConnected && this.isVerified) {\n this._monitorKeySecurity();\n }\n \n // 5. Global exposure monitoring (debug mode only)\n if (this._debugMode) {\n this._monitorGlobalExposure();\n }\n \n // 6. Heartbeat (if enabled and connected)\n if (this._heartbeatConfig && this._heartbeatConfig.enabled && this.isConnected()) {\n this._sendHeartbeat();\n }\n \n this._secureLog('info', '\uD83D\uDD27 Maintenance cycle completed successfully');\n \n } catch (error) {\n this._secureLog('error', '\u274C Maintenance cycle failed', {\n errorType: error?.constructor?.name || 'Unknown',\n message: error?.message || 'Unknown error'\n });\n \n // Emergency cleanup on failure\n this._emergencyCleanup();\n }\n }\n\n /**\n * Enforce hard resource limits with emergency cleanup\n */\n _enforceResourceLimits() {\n const violations = [];\n \n // Check log entries\n if (this._logCounts.size > this._resourceLimits.maxLogEntries) {\n violations.push('log_entries');\n }\n \n // Check message queue\n if (this.messageQueue.length > this._resourceLimits.maxMessageQueue) {\n violations.push('message_queue');\n }\n \n // Check IV history\n if (this._ivTrackingSystem && this._ivTrackingSystem.ivHistory.size > this._resourceLimits.maxIVHistory) {\n violations.push('iv_history');\n }\n \n // Check processed message IDs\n if (this.processedMessageIds.size > this._resourceLimits.maxProcessedMessageIds) {\n violations.push('processed_message_ids');\n }\n \n // Check decoy channels\n if (this.decoyChannels.size > this._resourceLimits.maxDecoyChannels) {\n violations.push('decoy_channels');\n }\n \n // Check fake traffic messages\n if (this._fakeTrafficMessages && this._fakeTrafficMessages.length > this._resourceLimits.maxFakeTrafficMessages) {\n violations.push('fake_traffic_messages');\n }\n \n // Check chunk queue\n if (this.chunkQueue.length > this._resourceLimits.maxChunkQueue) {\n violations.push('chunk_queue');\n }\n \n // Check packet buffer\n if (this.packetBuffer && this.packetBuffer.size > this._resourceLimits.maxPacketBuffer) {\n violations.push('packet_buffer');\n }\n \n // If violations detected, trigger emergency cleanup\n if (violations.length > 0) {\n this._secureLog('warn', '\u26A0\uFE0F Resource limit violations detected', { violations });\n this._emergencyCleanup();\n }\n }\n\n /**\n * Emergency cleanup when resource limits are exceeded\n */\n _emergencyCleanup() {\n this._secureLog('warn', '\uD83D\uDEA8 EMERGENCY: Resource limits exceeded, performing emergency cleanup');\n \n try {\n // 1. Clear all logs immediately\n this._logCounts.clear();\n this._secureLog('info', '\uD83E\uDDF9 Emergency: All logs cleared');\n \n // 2. Clear message queue\n this.messageQueue.length = 0;\n this._secureLog('info', '\uD83E\uDDF9 Emergency: Message queue cleared');\n \n // 3. Enhanced IV history cleanup\n if (this._ivTrackingSystem) {\n this._ivTrackingSystem.usedIVs.clear();\n this._ivTrackingSystem.ivHistory.clear();\n this._ivTrackingSystem.sessionIVs.clear();\n this._ivTrackingSystem.collisionCount = 0;\n this._ivTrackingSystem.emergencyMode = false;\n this._secureLog('info', '\uD83E\uDDF9 Enhanced Emergency: IV tracking system cleared');\n }\n \n // 4. Clear processed message IDs\n this.processedMessageIds.clear();\n this._secureLog('info', '\uD83E\uDDF9 Emergency: Processed message IDs cleared');\n \n // 5. Enhanced decoy channels cleanup\n if (this.decoyChannels) {\n for (const [channelName, timer] of this.decoyTimers) {\n if (timer) clearTimeout(timer);\n }\n this.decoyChannels.clear();\n this.decoyTimers.clear();\n this._secureLog('info', '\uD83E\uDDF9 Enhanced Emergency: Decoy channels cleared');\n }\n \n // 6. Enhanced fake traffic cleanup\n if (this.fakeTrafficTimer) {\n clearTimeout(this.fakeTrafficTimer);\n this.fakeTrafficTimer = null;\n }\n if (this._fakeTrafficMessages) {\n this._fakeTrafficMessages.length = 0;\n this._secureLog('info', '\uD83E\uDDF9 Enhanced Emergency: Fake traffic messages cleared');\n }\n \n // 7. Clear chunk queue\n this.chunkQueue.length = 0;\n this._secureLog('info', '\uD83E\uDDF9 Emergency: Chunk queue cleared');\n \n // 8. Clear packet buffer\n if (this.packetBuffer) {\n this.packetBuffer.clear();\n this._secureLog('info', '\uD83E\uDDF9 Emergency: Packet buffer cleared');\n }\n \n // 9. Enhanced memory cleanup with quantum-resistant patterns\n this._secureMemoryManager.isCleaning = true;\n this._secureMemoryManager.cleanupQueue.length = 0;\n this._secureMemoryManager.memoryStats.lastCleanup = Date.now();\n \n // Force multiple garbage collection cycles\n if (typeof window.gc === 'function') {\n try {\n // Multiple GC cycles for thorough cleanup\n for (let i = 0; i < 3; i++) {\n window.gc();\n this._secureLog('info', `\uD83E\uDDF9 Enhanced Emergency: Garbage collection cycle ${i + 1}/3`);\n // Small delay between cycles\n if (i < 2) {\n const start = Date.now();\n while (Date.now() - start < 10) {\n // Busy wait for 10ms\n }\n }\n }\n } catch (e) {\n // Ignore GC errors\n }\n }\n \n this._secureMemoryManager.isCleaning = false;\n \n this._secureLog('info', '\u2705 Enhanced emergency cleanup completed successfully');\n \n } catch (error) {\n this._secureLog('error', '\u274C Enhanced emergency cleanup failed', {\n errorType: error?.constructor?.name || 'Unknown',\n message: error?.message || 'Unknown error'\n });\n \n // Rollback mechanism (simplified)\n this._secureMemoryManager.isCleaning = false;\n }\n }\n\n /**\n * Validate emergency cleanup success\n * @param {Object} originalState - Original state before cleanup\n * @returns {Object} Validation results\n */\n _validateEmergencyCleanup(originalState) {\n const currentState = {\n messageQueueSize: this.messageQueue.length,\n processedIdsSize: this.processedMessageIds.size,\n packetBufferSize: this.packetBuffer ? this.packetBuffer.size : 0,\n ivTrackingSize: this._ivTrackingSystem ? this._ivTrackingSystem.usedIVs.size : 0,\n decoyChannelsSize: this.decoyChannels ? this.decoyChannels.size : 0\n };\n \n const validation = {\n messageQueueCleared: currentState.messageQueueSize === 0,\n processedIdsCleared: currentState.processedIdsSize === 0,\n packetBufferCleared: currentState.packetBufferSize === 0,\n ivTrackingCleared: currentState.ivTrackingSize === 0,\n decoyChannelsCleared: currentState.decoyChannelsSize === 0,\n allCleared: (\n currentState.messageQueueSize === 0 &&\n currentState.processedIdsSize === 0 &&\n currentState.packetBufferSize === 0 &&\n currentState.ivTrackingSize === 0 &&\n currentState.decoyChannelsSize === 0\n )\n };\n \n return validation;\n }\n\n /**\n * Cleanup resources based on age and usage\n */\n _cleanupResources() {\n const now = Date.now();\n \n // Clean old processed message IDs (keep only last hour)\n if (this.processedMessageIds.size > this._emergencyThresholds.processedMessageIds) {\n this.processedMessageIds.clear();\n this._secureLog('info', '\uD83E\uDDF9 Old processed message IDs cleared');\n }\n \n // Clean old IVs\n if (this._ivTrackingSystem) {\n this._cleanupOldIVs();\n }\n \n // Clean old keys\n this.cleanupOldKeys();\n \n // Clean rate limiter\n if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureCryptoUtils.rateLimiter) {\n window.EnhancedSecureCryptoUtils.rateLimiter.cleanup();\n }\n \n this._secureLog('info', '\uD83E\uDDF9 Resource cleanup completed');\n }\n\n /**\n * Monitor key security (replaces _startKeySecurityMonitoring)\n */\n _monitorKeySecurity() {\n if (this._keyStorageStats.activeKeys > 10) {\n this._secureLog('warn', '\u26A0\uFE0F High number of active keys detected. Consider rotation.');\n }\n \n if (Date.now() - (this._keyStorageStats.lastRotation || 0) > 3600000) {\n this._rotateKeys();\n }\n }\n\n /**\n * Send heartbeat message (called by unified scheduler)\n */\n _sendHeartbeat() {\n try {\n if (this.isConnected() && this.dataChannel && this.dataChannel.readyState === 'open') {\n this.dataChannel.send(JSON.stringify({ \n type: EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT, \n timestamp: Date.now() \n }));\n \n this._heartbeatConfig.lastHeartbeat = Date.now();\n this._secureLog('debug', '\uD83D\uDC93 Heartbeat sent');\n }\n } catch (error) {\n this._secureLog('error', '\u274C Heartbeat failed:', { \n errorType: error?.constructor?.name || 'Unknown',\n message: error?.message || 'Unknown error'\n });\n }\n }\n\n /**\n * Comprehensive input validation to prevent DoS and injection attacks\n * @param {any} data - Data to validate\n * @param {string} context - Context for validation (e.g., 'sendMessage', 'sendSecureMessage')\n * @returns {Object} Validation result with isValid and sanitizedData\n */\n _validateInputData(data, context = 'unknown') {\n const validationResult = {\n isValid: false,\n sanitizedData: null,\n errors: [],\n warnings: []\n };\n\n try {\n // 1. Basic type validation\n if (data === null || data === undefined) {\n validationResult.errors.push('Data cannot be null or undefined');\n return validationResult;\n }\n\n // 2. Size validation for strings\n if (typeof data === 'string') {\n if (data.length > this._inputValidationLimits.maxStringLength) {\n validationResult.errors.push(`String too long: ${data.length} > ${this._inputValidationLimits.maxStringLength}`);\n return validationResult;\n }\n\n // 3. Malicious pattern detection for strings\n for (const pattern of this._maliciousPatterns) {\n if (pattern.test(data)) {\n validationResult.errors.push(`Malicious pattern detected: ${pattern.source}`);\n this._secureLog('warn', '\uD83D\uDEA8 Malicious pattern detected in input', {\n context: context,\n pattern: pattern.source,\n dataLength: data.length\n });\n return validationResult;\n }\n }\n\n // 4. Sanitize string data\n validationResult.sanitizedData = this._sanitizeInputString(data);\n validationResult.isValid = true;\n return validationResult;\n }\n\n // 5. Object validation\n if (typeof data === 'object') {\n // Check for circular references\n const seen = new WeakSet();\n const checkCircular = (obj, path = '') => {\n if (obj === null || typeof obj !== 'object') return;\n \n if (seen.has(obj)) {\n validationResult.errors.push(`Circular reference detected at path: ${path}`);\n return;\n }\n \n seen.add(obj);\n \n // Check object depth\n if (path.split('.').length > this._inputValidationLimits.maxObjectDepth) {\n validationResult.errors.push(`Object too deep: ${path.split('.').length} > ${this._inputValidationLimits.maxObjectDepth}`);\n return;\n }\n\n // Check array length\n if (Array.isArray(obj) && obj.length > this._inputValidationLimits.maxArrayLength) {\n validationResult.errors.push(`Array too long: ${obj.length} > ${this._inputValidationLimits.maxArrayLength}`);\n return;\n }\n\n // Recursively check all properties\n for (const key in obj) {\n if (obj.hasOwnProperty(key)) {\n checkCircular(obj[key], path ? `${path}.${key}` : key);\n }\n }\n };\n\n checkCircular(data);\n \n if (validationResult.errors.length > 0) {\n return validationResult;\n }\n\n // 6. Check total object size\n const objectSize = this._calculateObjectSize(data);\n if (objectSize > this._inputValidationLimits.maxMessageSize) {\n validationResult.errors.push(`Object too large: ${objectSize} bytes > ${this._inputValidationLimits.maxMessageSize} bytes`);\n return validationResult;\n }\n\n // 7. Sanitize object data\n validationResult.sanitizedData = this._sanitizeInputObject(data);\n validationResult.isValid = true;\n return validationResult;\n }\n\n // 8. ArrayBuffer validation\n if (data instanceof ArrayBuffer) {\n if (data.byteLength > this._inputValidationLimits.maxMessageSize) {\n validationResult.errors.push(`ArrayBuffer too large: ${data.byteLength} bytes > ${this._inputValidationLimits.maxMessageSize} bytes`);\n return validationResult;\n }\n \n validationResult.sanitizedData = data;\n validationResult.isValid = true;\n return validationResult;\n }\n\n // 9. Other types are not allowed\n validationResult.errors.push(`Unsupported data type: ${typeof data}`);\n return validationResult;\n\n } catch (error) {\n validationResult.errors.push(`Validation error: ${error.message}`);\n this._secureLog('error', '\u274C Input validation failed', {\n context: context,\n errorType: error?.constructor?.name || 'Unknown',\n message: error?.message || 'Unknown error'\n });\n return validationResult;\n }\n }\n\n /**\n * Calculate approximate object size in bytes\n * @param {any} obj - Object to calculate size for\n * @returns {number} Size in bytes\n */\n _calculateObjectSize(obj) {\n try {\n const jsonString = JSON.stringify(obj);\n return new TextEncoder().encode(jsonString).length;\n } catch (error) {\n // If JSON.stringify fails, estimate size\n return 1024 * 1024; // Assume 1MB to be safe\n }\n }\n\n /**\n * Sanitize string data for input validation\n * @param {string} str - String to sanitize\n * @returns {string} Sanitized string\n */\n _sanitizeInputString(str) {\n if (typeof str !== 'string') return str;\n \n // Remove null bytes\n str = str.replace(/\\0/g, '');\n \n // Normalize whitespace\n str = str.replace(/\\s+/g, ' ');\n \n // Trim\n str = str.trim();\n \n return str;\n }\n\n /**\n * Sanitize object data for input validation\n * @param {any} obj - Object to sanitize\n * @returns {any} Sanitized object\n */\n _sanitizeInputObject(obj) {\n if (obj === null || typeof obj !== 'object') return obj;\n \n if (Array.isArray(obj)) {\n return obj.map(item => this._sanitizeInputObject(item));\n }\n \n const sanitized = {};\n for (const key in obj) {\n if (obj.hasOwnProperty(key)) {\n const value = obj[key];\n if (typeof value === 'string') {\n sanitized[key] = this._sanitizeInputString(value);\n } else if (typeof value === 'object') {\n sanitized[key] = this._sanitizeInputObject(value);\n } else {\n sanitized[key] = value;\n }\n }\n }\n \n return sanitized;\n }\n\n /**\n * Rate limiting for message sending\n * @param {string} context - Context for rate limiting\n * @returns {boolean} true if rate limit allows\n */\n _checkRateLimit(context = 'message') {\n const now = Date.now();\n \n // Initialize rate limiter if not exists\n if (!this._rateLimiter) {\n this._rateLimiter = {\n messageCount: 0,\n lastReset: now,\n burstCount: 0,\n lastBurstReset: now\n };\n }\n \n // Reset counters if needed\n if (now - this._rateLimiter.lastReset > 60000) { // 1 minute\n this._rateLimiter.messageCount = 0;\n this._rateLimiter.lastReset = now;\n }\n \n if (now - this._rateLimiter.lastBurstReset > 1000) { // 1 second\n this._rateLimiter.burstCount = 0;\n this._rateLimiter.lastBurstReset = now;\n }\n \n // Check burst limit\n if (this._rateLimiter.burstCount >= this._inputValidationLimits.rateLimitBurstSize) {\n this._secureLog('warn', '\u26A0\uFE0F Rate limit burst exceeded', { context });\n return false;\n }\n \n // Check overall rate limit\n if (this._rateLimiter.messageCount >= this._inputValidationLimits.rateLimitMessagesPerMinute) {\n this._secureLog('warn', '\u26A0\uFE0F Rate limit exceeded', { context });\n return false;\n }\n \n // Increment counters\n this._rateLimiter.messageCount++;\n this._rateLimiter.burstCount++;\n \n return true;\n }\n\n // ============================================\n // SECURE KEY STORAGE MANAGEMENT\n // ============================================\n\n /**\n * Initializes the secure key storage\n */\n _initializeSecureKeyStorage() {\n // Initialize with the new class\n this._secureKeyStorage = new SecureKeyStorage();\n \n // Keep the stats structure for compatibility\n this._keyStorageStats = {\n totalKeys: 0,\n activeKeys: 0,\n lastAccess: null,\n lastRotation: null,\n };\n \n this._secureLog('info', '\uD83D\uDD10 Enhanced secure key storage initialized');\n }\n\n // Helper: ensure file transfer system is ready (lazy init on receiver)\n async _ensureFileTransferReady() {\n try {\n // If already initialized \u2014 done\n if (this.fileTransferSystem) {\n return true;\n }\n // Requires an open data channel and a verified connection\n if (!this.dataChannel || this.dataChannel.readyState !== 'open') {\n throw new Error('Data channel not open');\n }\n if (!this.isVerified) {\n throw new Error('Connection not verified');\n }\n // Initialization\n this.initializeFileTransfer();\n \n // \u041A\u0420\u0418\u0422\u0418\u0427\u0415\u0421\u041A\u041E\u0415 \u0418\u0421\u041F\u0420\u0410\u0412\u041B\u0415\u041D\u0418\u0415: \u0416\u0434\u0435\u043C \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 \u0442\u0430\u0439\u043C\u0430\u0443\u0442\u043E\u043C\n let attempts = 0;\n const maxAttempts = 50; // 5 \u0441\u0435\u043A\u0443\u043D\u0434 \u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C\n while (!this.fileTransferSystem && attempts < maxAttempts) {\n await new Promise(r => setTimeout(r, 100));\n attempts++;\n }\n \n if (!this.fileTransferSystem) {\n throw new Error('File transfer system initialization timeout');\n }\n \n return true;\n } catch (e) {\n this._secureLog('error', '\u274C _ensureFileTransferReady failed', { \n errorType: e?.constructor?.name || 'Unknown',\n hasMessage: !!e?.message \n });\n return false;\n }\n }\n\n _getSecureKey(keyId) {\n return this._secureKeyStorage.retrieveKey(keyId);\n }\n\n async _setSecureKey(keyId, key) {\n if (!(key instanceof CryptoKey)) {\n this._secureLog('error', '\u274C Attempt to store non-CryptoKey');\n return false;\n }\n \n const success = await this._secureKeyStorage.storeKey(keyId, key, {\n version: this.currentKeyVersion,\n type: key.algorithm.name\n });\n \n if (success) {\n this._secureLog('info', `\uD83D\uDD11 Key ${keyId} stored securely with encryption`);\n }\n \n return success;\n }\n\n /**\n * Validates a key value\n * @param {CryptoKey} key - Key to validate\n * @returns {boolean} true if the key is valid\n */\n _validateKeyValue(key) {\n return key instanceof CryptoKey &&\n key.algorithm &&\n key.usages &&\n key.usages.length > 0;\n }\n\n _secureWipeKeys() {\n this._secureKeyStorage.secureWipeAll();\n this._secureLog('info', '\uD83E\uDDF9 All keys securely wiped and encrypted storage cleared');\n }\n\n /**\n * Validates key storage state\n * @returns {boolean} true if the storage is ready\n */\n _validateKeyStorage() {\n return this._secureKeyStorage instanceof SecureKeyStorage;\n }\n\n /**\n * Returns secure key storage statistics\n * @returns {object} Storage metrics\n */\n _getKeyStorageStats() {\n const stats = this._secureKeyStorage.getStorageStats();\n return {\n totalKeysCount: stats.totalKeys,\n activeKeysCount: stats.totalKeys,\n hasLastAccess: stats.metadata.some(m => m.lastAccessed),\n hasLastRotation: !!this._keyStorageStats.lastRotation,\n storageType: 'SecureKeyStorage',\n timestamp: Date.now()\n };\n }\n\n /**\n * Performs key rotation in storage\n */\n _rotateKeys() {\n const oldKeys = Array.from(this._secureKeyStorage.keys());\n this._secureKeyStorage.clear();\n this._keyStorageStats.lastRotation = Date.now();\n this._keyStorageStats.activeKeys = 0;\n this._secureLog('info', `\uD83D\uDD04 Key rotation completed. ${oldKeys.length} keys rotated`);\n }\n\n /**\n * Emergency key wipe (e.g., upon detecting a threat)\n */\n _emergencyKeyWipe() {\n this._secureWipeKeys();\n this._secureLog('error', '\uD83D\uDEA8 EMERGENCY: All keys wiped due to security threat');\n }\n\n /**\n * Starts key security monitoring\n * @deprecated Use unified scheduler instead\n */\n _startKeySecurityMonitoring() {\n // Functionality moved to unified scheduler\n this._secureLog('info', '\uD83D\uDD27 Key security monitoring moved to unified scheduler');\n }\n\n\n // ============================================\n // HELPER METHODS\n // ============================================\n /**\n * Constant-time key validation to prevent timing attacks\n * @param {CryptoKey} key - Key to validate\n * @returns {boolean} true if key is valid\n */\n _validateKeyConstantTime(key) {\n // Constant-time validation to prevent timing attacks\n let isValid = 0;\n \n // Check if key is CryptoKey instance (constant-time)\n try {\n const isCryptoKey = key instanceof CryptoKey;\n isValid += isCryptoKey ? 1 : 0;\n } catch {\n isValid += 0;\n }\n \n // Check algorithm (constant-time)\n try {\n const hasAlgorithm = !!(key && key.algorithm);\n isValid += hasAlgorithm ? 1 : 0;\n } catch {\n isValid += 0;\n }\n \n // Check type (constant-time)\n try {\n const hasType = !!(key && key.type);\n isValid += hasType ? 1 : 0;\n } catch {\n isValid += 0;\n }\n \n // Check extractable property (constant-time)\n try {\n const hasExtractable = key && key.extractable !== undefined;\n isValid += hasExtractable ? 1 : 0;\n } catch {\n isValid += 0;\n }\n \n // All checks must pass\n return isValid === 4;\n }\n\n /**\n * Constant-time key pair validation\n * @param {Object} keyPair - Key pair to validate\n * @returns {boolean} true if key pair is valid\n */\n _validateKeyPairConstantTime(keyPair) {\n if (!keyPair || typeof keyPair !== 'object') return false;\n \n const privateKeyValid = this._validateKeyConstantTime(keyPair.privateKey);\n const publicKeyValid = this._validateKeyConstantTime(keyPair.publicKey);\n \n // Constant-time AND operation\n return privateKeyValid && publicKeyValid;\n }\n\n /**\n * Enhanced secure logging system initialization\n */\n _initializeSecureLogging() {\n // Logging levels\n this._logLevels = {\n error: 0,\n warn: 1, \n info: 2,\n debug: 3,\n trace: 4\n };\n \n // Ultra-strict levels for production\n this._currentLogLevel = this._isProductionMode ? \n this._logLevels.error : // In production, ONLY critical errors\n this._logLevels.info; // In development, up to info\n \n // Reduced log limits to prevent data accumulation\n this._logCounts = new Map();\n this._maxLogCount = this._isProductionMode ? 5 : 50; // Reduced limits\n \n // Hard resource limits to prevent memory leaks\n this._resourceLimits = {\n maxLogEntries: this._isProductionMode ? 100 : 1000,\n maxMessageQueue: 1000,\n maxIVHistory: 10000,\n maxProcessedMessageIds: 5000,\n maxDecoyChannels: 100,\n maxFakeTrafficMessages: 500,\n maxChunkQueue: 200,\n maxPacketBuffer: 1000\n };\n \n // Emergency cleanup thresholds\n this._emergencyThresholds = {\n logEntries: this._resourceLimits.maxLogEntries * 0.8, // 80%\n messageQueue: this._resourceLimits.maxMessageQueue * 0.8,\n ivHistory: this._resourceLimits.maxIVHistory * 0.8,\n processedMessageIds: this._resourceLimits.maxProcessedMessageIds * 0.8\n };\n \n // Input validation limits to prevent DoS attacks\n this._inputValidationLimits = {\n maxStringLength: 100000, // 100KB for strings\n maxObjectDepth: 10, // Maximum object nesting depth\n maxArrayLength: 1000, // Maximum array length\n maxMessageSize: 1024 * 1024, // 1MB total message size\n maxConcurrentMessages: 10, // Maximum concurrent message processing\n rateLimitMessagesPerMinute: 60, // Rate limiting\n rateLimitBurstSize: 10 // Burst size for rate limiting\n };\n \n // Malicious pattern detection\n this._maliciousPatterns = [\n /)<[^<]*)*<\\/script>/gi, // Script tags\n /javascript:/gi, // JavaScript protocol\n /data:text\\/html/gi, // Data URLs with HTML\n /on\\w+\\s*=/gi, // Event handlers\n /eval\\s*\\(/gi, // eval() calls\n /document\\./gi, // Document object access\n /window\\./gi, // Window object access\n /localStorage/gi, // LocalStorage access\n /sessionStorage/gi, // SessionStorage access\n /fetch\\s*\\(/gi, // Fetch API calls\n /XMLHttpRequest/gi, // XHR calls\n /import\\s*\\(/gi, // Dynamic imports\n /require\\s*\\(/gi, // Require calls\n /process\\./gi, // Process object access\n /global/gi, // Global object access\n /__proto__/gi, // Prototype pollution\n /constructor/gi, // Constructor access\n /prototype/gi, // Prototype access\n /toString\\s*\\(/gi, // toString calls\n /valueOf\\s*\\(/gi // valueOf calls\n ];\n\n // Comprehensive blacklist with all sensitive patterns\n this._absoluteBlacklist = new Set([\n // Cryptographic keys\n 'encryptionKey', 'macKey', 'metadataKey', 'privateKey', 'publicKey',\n 'ecdhKeyPair', 'ecdsaKeyPair', 'peerPublicKey', 'nestedEncryptionKey',\n \n // Authentication and session data\n 'verificationCode', 'sessionSalt', 'keyFingerprint', 'sessionId',\n 'authChallenge', 'authProof', 'authToken', 'sessionToken',\n \n // Credentials and secrets\n 'password', 'token', 'secret', 'credential', 'signature',\n 'apiKey', 'accessKey', 'secretKey', 'privateKey',\n \n // Cryptographic materials\n 'hash', 'digest', 'nonce', 'iv', 'cipher', 'seed',\n 'entropy', 'random', 'salt', 'fingerprint',\n \n // JWT and session data\n 'jwt', 'bearer', 'refreshToken', 'accessToken',\n \n // File transfer sensitive data\n 'fileHash', 'fileSignature', 'transferKey', 'chunkKey'\n ]);\n\n // Minimal whitelist with strict validation\n this._safeFieldsWhitelist = new Set([\n // Basic status fields\n 'timestamp', 'type', 'status', 'state', 'level',\n 'isConnected', 'isVerified', 'isInitiator', 'version',\n \n // Counters and metrics (safe)\n 'count', 'total', 'active', 'inactive', 'success', 'failure',\n \n // Connection states (safe)\n 'readyState', 'connectionState', 'iceConnectionState',\n \n // Feature counts (safe)\n 'activeFeaturesCount', 'totalFeatures', 'stage',\n \n // Error types (safe)\n 'errorType', 'errorCode', 'phase', 'attempt'\n ]);\n \n // Initialize security monitoring\n this._initializeLogSecurityMonitoring();\n \n this._secureLog('info', `\uD83D\uDD27 Enhanced secure logging initialized (Production: ${this._isProductionMode})`);\n }\n\n /**\n * Initialize security monitoring for logging system\n */\n _initializeLogSecurityMonitoring() {\n // Security monitoring moved to unified scheduler\n this._logSecurityViolations = 0;\n this._maxLogSecurityViolations = 3;\n }\n\n /**\n * Audit logging system security\n */\n _auditLoggingSystemSecurity() {\n let violations = 0;\n \n // Check for excessive log counts (potential data leakage)\n for (const [key, count] of this._logCounts.entries()) {\n if (count > this._maxLogCount * 2) {\n violations++;\n this._originalConsole?.error?.(`\uD83D\uDEA8 LOG SECURITY: Excessive log count detected: ${key}`);\n }\n }\n \n // Check for blacklisted patterns in recent logs\n const recentLogs = Array.from(this._logCounts.keys());\n for (const logKey of recentLogs) {\n if (this._containsSensitiveContent(logKey)) {\n violations++;\n this._originalConsole?.error?.(`\uD83D\uDEA8 LOG SECURITY: Sensitive content in log key: ${logKey}`);\n }\n }\n \n // Emergency shutdown if too many violations\n this._logSecurityViolations += violations;\n if (this._logSecurityViolations >= this._maxLogSecurityViolations) {\n this._emergencyDisableLogging();\n this._originalConsole?.error?.('\uD83D\uDEA8 CRITICAL: Logging system disabled due to security violations');\n }\n }\n /**\n * Shim to redirect arbitrary console.log calls to _secureLog('info', ...)\n * Fixed syntax errors and improved error handling\n */\n _secureLogShim(...args) {\n try {\n // Validate arguments array\n if (!Array.isArray(args) || args.length === 0) {\n return;\n }\n \n // Proper destructuring with fallback\n const message = args[0];\n const restArgs = args.slice(1);\n \n // Handle different argument patterns\n if (restArgs.length === 0) {\n this._secureLog('info', String(message || ''));\n return;\n }\n \n if (restArgs.length === 1) {\n this._secureLog('info', String(message || ''), restArgs[0]);\n return;\n }\n \n // Proper object structure for multiple args\n this._secureLog('info', String(message || ''), { \n additionalArgs: restArgs,\n argCount: restArgs.length \n });\n } catch (error) {\n // Better error handling - fallback to original console if available\n try {\n if (this._originalConsole?.log) {\n this._originalConsole.log(...args);\n }\n } catch (fallbackError) {\n // Silent failure to prevent execution disruption\n }\n }\n }\n /**\n * Redirects global console.log to this instance's secure logger\n * Improved error handling and validation\n */\n /**\n * Setup own logger without touching global console\n */\n _setupOwnLogger() {\n // Create own logger without touching global console\n this.logger = {\n log: (message, data) => this._secureLog('info', message, data),\n info: (message, data) => this._secureLog('info', message, data),\n warn: (message, data) => this._secureLog('warn', message, data),\n error: (message, data) => this._secureLog('error', message, data),\n debug: (message, data) => this._secureLog('debug', message, data)\n };\n \n // In development, log to console; in production, use secure logging only\n if (EnhancedSecureWebRTCManager.DEBUG_MODE) {\n this._secureLog('info', '\uD83D\uDD12 Own logger created - development mode');\n } else {\n this._secureLog('info', '\uD83D\uDD12 Own logger created - production mode');\n }\n }\n /**\n * Production logging - use own logger with minimal output\n */\n _setupProductionLogging() {\n // In production, own logger becomes minimal\n if (this._isProductionMode) {\n this.logger = {\n log: () => {}, // No-op in production\n info: () => {}, // No-op in production\n warn: (message, data) => this._secureLog('warn', message, data),\n error: (message, data) => this._secureLog('error', message, data),\n debug: () => {} // No-op in production\n };\n \n this._secureLog('info', '\uD83D\uDD12 Production logging mode activated');\n }\n }\n /**\n * Secure logging with enhanced data protection\n * @param {string} level - Log level (error, warn, info, debug, trace)\n * @param {string} message - Message\n * @param {object} data - Optional payload (will be sanitized)\n */\n _secureLog(level, message, data = null) {\n // Pre-sanitization audit to prevent data leakage\n if (data && !this._auditLogMessage(message, data)) {\n // Log the attempt but block the actual data\n this._originalConsole?.error?.('\uD83D\uDEA8 SECURITY: Logging blocked due to potential data leakage');\n return;\n }\n \n // Check log level\n if (this._logLevels[level] > this._currentLogLevel) {\n return;\n }\n \n // Prevent log spam with better key generation\n const logKey = `${level}:${message.substring(0, 50)}`;\n const currentCount = this._logCounts.get(logKey) || 0;\n \n if (currentCount >= this._maxLogCount) {\n return;\n }\n \n this._logCounts.set(logKey, currentCount + 1);\n \n // Enhanced sanitization with multiple passes\n let sanitizedData = null;\n if (data) {\n // First pass: basic sanitization\n sanitizedData = this._sanitizeLogData(data);\n \n // Second pass: check if sanitized data still contains sensitive content\n if (this._containsSensitiveContent(JSON.stringify(sanitizedData))) {\n this._originalConsole?.error?.('\uD83D\uDEA8 SECURITY: Sanitized data still contains sensitive content - blocking log');\n return;\n }\n }\n \n // Production mode security - only log essential errors\n if (this._isProductionMode) {\n if (level === 'error') {\n // In production, only log error messages without sensitive data\n const safeMessage = this._sanitizeString(message);\n this._originalConsole?.error?.(safeMessage);\n }\n // Block all other log levels in production\n return;\n }\n \n // Development mode: full logging with sanitized data\n const logMethod = this._originalConsole?.[level] || this._originalConsole?.log;\n if (sanitizedData) {\n logMethod(message, sanitizedData);\n } else {\n logMethod(message);\n }\n }\n /**\n * Enhanced sanitization for log data with multiple security layers\n */\n _sanitizeLogData(data) {\n // Pre-check for sensitive content before processing\n if (typeof data === 'string') {\n return this._sanitizeString(data);\n }\n \n if (!data || typeof data !== 'object') {\n return data;\n }\n \n const sanitized = {};\n \n for (const [key, value] of Object.entries(data)) {\n const lowerKey = key.toLowerCase();\n \n // Enhanced blacklist with more comprehensive patterns\n const blacklistPatterns = [\n 'key', 'secret', 'token', 'password', 'credential', 'auth',\n 'fingerprint', 'salt', 'signature', 'private', 'encryption',\n 'mac', 'metadata', 'session', 'jwt', 'bearer', 'hash',\n 'digest', 'nonce', 'iv', 'cipher', 'seed', 'entropy'\n ];\n \n const isBlacklisted = this._absoluteBlacklist.has(key) || \n blacklistPatterns.some(pattern => lowerKey.includes(pattern));\n \n if (isBlacklisted) {\n sanitized[key] = '[SENSITIVE_DATA_BLOCKED]';\n continue;\n }\n \n // Enhanced whitelist with strict validation\n if (this._safeFieldsWhitelist.has(key)) {\n // Even whitelisted fields get sanitized if they contain sensitive data\n if (typeof value === 'string') {\n sanitized[key] = this._sanitizeString(value);\n } else {\n sanitized[key] = value;\n }\n continue;\n }\n \n // Enhanced type handling with security checks\n if (typeof value === 'boolean' || typeof value === 'number') {\n sanitized[key] = value;\n } else if (typeof value === 'string') {\n sanitized[key] = this._sanitizeString(value);\n } else if (value instanceof ArrayBuffer || value instanceof Uint8Array) {\n // Don't reveal actual byte lengths for security\n sanitized[key] = `[${value.constructor.name}( bytes)]`;\n } else if (value && typeof value === 'object') {\n // Recursive sanitization with depth limit and security check\n try {\n sanitized[key] = this._sanitizeLogData(value);\n } catch (error) {\n sanitized[key] = '[RECURSIVE_SANITIZATION_FAILED]';\n }\n } else {\n sanitized[key] = `[${typeof value}]`;\n }\n }\n \n // Final security check on sanitized data\n const sanitizedString = JSON.stringify(sanitized);\n if (this._containsSensitiveContent(sanitizedString)) {\n return { error: 'SANITIZATION_FAILED_SENSITIVE_CONTENT_DETECTED' };\n }\n \n return sanitized;\n }\n /**\n * Enhanced sanitization for strings with comprehensive pattern detection\n */\n _sanitizeString(str) {\n if (typeof str !== 'string' || str.length === 0) {\n return str;\n }\n \n // Comprehensive sensitive pattern detection\n const sensitivePatterns = [\n // Hex patterns (various lengths)\n /[a-f0-9]{16,}/i, // 16+ hex chars (covers short keys)\n /[a-f0-9]{8,}/i, // 8+ hex chars (covers shorter keys)\n \n // Base64 patterns (comprehensive)\n /[A-Za-z0-9+/]{16,}={0,2}/, // Base64 with padding\n /[A-Za-z0-9+/]{12,}/, // Base64 without padding\n /[A-Za-z0-9+/=]{10,}/, // Base64-like patterns\n \n // Base58 patterns (Bitcoin-style)\n /[1-9A-HJ-NP-Za-km-z]{16,}/, // Base58 strings\n \n // Base32 patterns\n /[A-Z2-7]{16,}={0,6}/, // Base32 with padding\n /[A-Z2-7]{12,}/, // Base32 without padding\n \n // Custom encoding patterns\n /[A-Za-z0-9\\-_]{16,}/, // URL-safe base64 variants\n /[A-Za-z0-9\\.\\-_]{16,}/, // JWT-like patterns\n \n // Long alphanumeric strings (potential keys)\n /\\b[A-Za-z0-9]{12,}\\b/, // 12+ alphanumeric chars\n /\\b[A-Za-z0-9]{8,}\\b/, // 8+ alphanumeric chars\n \n // PEM key patterns\n /BEGIN\\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\\s+KEY/i,\n /END\\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\\s+KEY/i,\n \n // JWT patterns\n /^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$/,\n \n // API key patterns\n /(api[_-]?key|token|secret|password|credential)[\\s]*[:=][\\s]*[A-Za-z0-9\\-_]{8,}/i,\n \n // UUID patterns\n /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i,\n \n // Credit cards and SSN (existing patterns)\n /\\b\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}\\b/,\n /\\b\\d{3}-\\d{2}-\\d{4}\\b/,\n \n // Email patterns (more restrictive)\n /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/,\n \n // Crypto-specific patterns\n /(fingerprint|hash|digest|signature)[\\s]*[:=][\\s]*[A-Za-z0-9\\-_]{8,}/i,\n /(encryption|mac|metadata)[\\s]*key[\\s]*[:=][\\s]*[A-Za-z0-9\\-_]{8,}/i,\n \n // Session and auth patterns\n /(session|auth|jwt|bearer)[\\s]*[:=][\\s]*[A-Za-z0-9\\-_]{8,}/i,\n ];\n \n // Check for sensitive patterns with early return\n for (const pattern of sensitivePatterns) {\n if (pattern.test(str)) {\n // Always fully hide sensitive data\n return '[SENSITIVE_DATA_REDACTED]';\n }\n }\n \n // Check for suspicious entropy (high randomness indicates keys)\n if (this._hasHighEntropy(str)) {\n return '[HIGH_ENTROPY_DATA_REDACTED]';\n }\n \n // Check for suspicious character distributions\n if (this._hasSuspiciousDistribution(str)) {\n return '[SUSPICIOUS_DATA_REDACTED]';\n }\n \n // For regular strings \u2014 limit length more aggressively\n if (str.length > 50) {\n return str.substring(0, 20) + '...[TRUNCATED]';\n }\n \n return str;\n }\n /**\n * Enhanced sensitive content detection\n */\n _containsSensitiveContent(str) {\n if (typeof str !== 'string') return false;\n \n // Use the same comprehensive patterns as _sanitizeString\n const sensitivePatterns = [\n /[a-f0-9]{16,}/i,\n /[A-Za-z0-9+/]{16,}={0,2}/,\n /[1-9A-HJ-NP-Za-km-z]{16,}/,\n /[A-Z2-7]{16,}={0,6}/,\n /\\b[A-Za-z0-9]{12,}\\b/,\n /BEGIN\\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\\s+KEY/i,\n /^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$/,\n /(api[_-]?key|token|secret|password|credential)[\\s]*[:=][\\s]*[A-Za-z0-9\\-_]{8,}/i,\n ];\n \n return sensitivePatterns.some(pattern => pattern.test(str)) ||\n this._hasHighEntropy(str) ||\n this._hasSuspiciousDistribution(str);\n }\n\n /**\n * Check for high entropy strings (likely cryptographic keys)\n */\n _hasHighEntropy(str) {\n if (str.length < 8) return false;\n \n // Calculate character frequency\n const charCount = {};\n for (const char of str) {\n charCount[char] = (charCount[char] || 0) + 1;\n }\n \n // Calculate Shannon entropy\n const length = str.length;\n let entropy = 0;\n \n for (const count of Object.values(charCount)) {\n const probability = count / length;\n entropy -= probability * Math.log2(probability);\n }\n \n // High entropy (>4.5 bits per character) suggests cryptographic data\n return entropy > 4.5;\n }\n\n /**\n * Check for suspicious character distributions\n */\n _hasSuspiciousDistribution(str) {\n if (str.length < 8) return false;\n \n // Check for uniform distribution of hex characters\n const hexChars = str.match(/[a-f0-9]/gi) || [];\n if (hexChars.length >= str.length * 0.8) {\n // If 80%+ are hex chars, likely a key\n return true;\n }\n \n // Check for base64-like distribution\n const base64Chars = str.match(/[A-Za-z0-9+/=]/g) || [];\n if (base64Chars.length >= str.length * 0.9) {\n // If 90%+ are base64 chars, likely encoded data\n return true;\n }\n \n // Check for very low character diversity (suggests random data)\n const uniqueChars = new Set(str).size;\n const diversityRatio = uniqueChars / str.length;\n \n // If diversity is too high (>0.8) for the length, likely random data\n if (diversityRatio > 0.8 && str.length > 16) {\n return true;\n }\n \n return false;\n }\n\n\n // ============================================\n // SECURE LOGGING SYSTEM\n // ============================================\n \n /**\n * Detects production mode\n */\n _detectProductionMode() {\n // Check various production mode indicators\n return (\n // Standard env variables\n (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') ||\n // No debug flags\n (!this._debugMode) ||\n // Production domains\n (window.location.hostname && !window.location.hostname.includes('localhost') && \n !window.location.hostname.includes('127.0.0.1') && \n !window.location.hostname.includes('.local')) ||\n // Minified code (heuristic check)\n (typeof window.webpackHotUpdate === 'undefined' && !window.location.search.includes('debug'))\n );\n }\n // ============================================\n // FIXED SECURE GLOBAL API\n // ============================================\n \n /**\n * Sets up a secure global API with limited access\n */\n _setupSecureGlobalAPI() {\n // Log that we're starting API setup\n this._secureLog('info', '\uD83D\uDD12 Starting secure global API setup');\n \n // Create simple public API with safety checks\n const secureAPI = {};\n \n // Only bind methods that exist\n if (typeof this.sendMessage === 'function') {\n secureAPI.sendMessage = this.sendMessage.bind(this);\n }\n \n // Create simple getConnectionStatus method\n secureAPI.getConnectionStatus = () => ({\n isConnected: this.isConnected ? this.isConnected() : false,\n isVerified: this.isVerified || false,\n connectionState: this.peerConnection?.connectionState || 'disconnected'\n });\n \n // Create simple getSecurityStatus method\n secureAPI.getSecurityStatus = () => ({\n securityLevel: this.currentSecurityLevel || 'basic',\n stage: 'initialized',\n activeFeaturesCount: Object.values(this.securityFeatures || {}).filter(Boolean).length\n });\n \n if (typeof this.sendFile === 'function') {\n secureAPI.sendFile = this.sendFile.bind(this);\n }\n \n // Create simple getFileTransferStatus method\n secureAPI.getFileTransferStatus = () => ({\n initialized: !!this.fileTransferSystem,\n status: 'ready',\n activeTransfers: 0,\n receivingTransfers: 0\n });\n \n if (typeof this.disconnect === 'function') {\n secureAPI.disconnect = this.disconnect.bind(this);\n }\n \n // Create simple API object with safety checks\n const safeGlobalAPI = {\n ...secureAPI, // Spread only existing methods\n getConfiguration: () => ({\n fakeTraffic: this._config.fakeTraffic.enabled,\n decoyChannels: this._config.decoyChannels.enabled,\n packetPadding: this._config.packetPadding.enabled,\n antiFingerprinting: this._config.antiFingerprinting.enabled\n }),\n emergency: {}\n };\n \n // Only add emergency methods that exist\n if (typeof this._emergencyUnlockAllMutexes === 'function') {\n safeGlobalAPI.emergency.unlockAllMutexes = this._emergencyUnlockAllMutexes.bind(this);\n }\n \n if (typeof this._emergencyRecoverMutexSystem === 'function') {\n safeGlobalAPI.emergency.recoverMutexSystem = this._emergencyRecoverMutexSystem.bind(this);\n }\n \n if (typeof this._emergencyDisableLogging === 'function') {\n safeGlobalAPI.emergency.disableLogging = this._emergencyDisableLogging.bind(this);\n }\n \n if (typeof this._resetLoggingSystem === 'function') {\n safeGlobalAPI.emergency.resetLogging = this._resetLoggingSystem.bind(this);\n }\n \n // Add file transfer system status\n safeGlobalAPI.getFileTransferSystemStatus = () => ({\n initialized: !!this.fileTransferSystem,\n status: 'ready',\n activeTransfers: 0,\n receivingTransfers: 0\n });\n \n // Log available methods for debugging\n this._secureLog('info', '\uD83D\uDD12 API methods available', {\n sendMessage: !!secureAPI.sendMessage,\n getConnectionStatus: !!secureAPI.getConnectionStatus,\n getSecurityStatus: !!secureAPI.getSecurityStatus,\n sendFile: !!secureAPI.sendFile,\n getFileTransferStatus: !!secureAPI.getFileTransferStatus,\n disconnect: !!secureAPI.disconnect,\n getConfiguration: !!safeGlobalAPI.getConfiguration,\n emergencyMethods: Object.keys(safeGlobalAPI.emergency).length\n });\n\n // Apply Object.freeze to prevent modification\n Object.freeze(safeGlobalAPI);\n Object.freeze(safeGlobalAPI.emergency);\n\n // Export API once without monitoring\n this._createProtectedGlobalAPI(safeGlobalAPI);\n \n // Setup minimal protection\n this._setupMinimalGlobalProtection();\n \n // Log that API setup is complete\n this._secureLog('info', '\uD83D\uDD12 Secure global API setup completed successfully');\n }\n /**\n * Create simple global API export\n */\n _createProtectedGlobalAPI(safeGlobalAPI) {\n // Log that we're creating protected global API\n this._secureLog('info', '\uD83D\uDD12 Creating protected global API');\n \n // Simple API export without proxy or monitoring\n if (!window.secureBitChat) {\n this._exportAPI(safeGlobalAPI);\n } else {\n this._secureLog('warn', '\u26A0\uFE0F Global API already exists, skipping setup');\n }\n }\n \n /**\n * Simple API export without monitoring\n */\n _exportAPI(apiObject) {\n // Log that we're exporting API\n this._secureLog('info', '\uD83D\uDD12 Exporting API to window.secureBitChat');\n \n // Check if important methods are available\n if (!this._importantMethods || !this._importantMethods.defineProperty) {\n this._secureLog('error', '\u274C Important methods not available for API export, using fallback');\n // Fallback to direct Object.defineProperty\n Object.defineProperty(window, 'secureBitChat', {\n value: apiObject,\n writable: false,\n configurable: false,\n enumerable: true\n });\n } else {\n // One-time export with immutable properties\n this._importantMethods.defineProperty(window, 'secureBitChat', {\n value: apiObject,\n writable: false,\n configurable: false,\n enumerable: true\n });\n }\n \n this._secureLog('info', '\uD83D\uDD12 Secure API exported to window.secureBitChat');\n }\n \n /**\n * Setup minimal global protection\n */\n _setupMinimalGlobalProtection() {\n // Simple protection without monitoring (methods already stored)\n this._protectGlobalAPI();\n \n this._secureLog('info', '\uD83D\uDD12 Minimal global protection activated');\n }\n \n /**\n * Store important methods in closure for local use\n */\n _storeImportantMethods() {\n // Store references to important methods locally\n this._importantMethods = {\n defineProperty: Object.defineProperty,\n getOwnPropertyDescriptor: Object.getOwnPropertyDescriptor,\n freeze: Object.freeze,\n consoleLog: console.log,\n consoleError: console.error,\n consoleWarn: console.warn\n };\n \n this._secureLog('info', '\uD83D\uDD12 Important methods stored locally', {\n defineProperty: !!this._importantMethods.defineProperty,\n getOwnPropertyDescriptor: !!this._importantMethods.getOwnPropertyDescriptor,\n freeze: !!this._importantMethods.freeze\n });\n }\n\n /**\n * Simple protection without monitoring\n */\n _setupSimpleProtection() {\n this._secureLog('info', '\uD83D\uDD12 Simple protection activated - no monitoring');\n }\n\n /**\n * No global exposure prevention needed\n */\n _preventGlobalExposure() {\n this._secureLog('info', '\uD83D\uDD12 No global exposure prevention - using secure API export only');\n }\n /**\n * API integrity check - only at initialization\n */\n _verifyAPIIntegrity() {\n try {\n if (!window.secureBitChat) {\n this._secureLog('error', '\u274C SECURITY ALERT: Secure API has been removed!');\n return false;\n }\n \n const requiredMethods = ['sendMessage', 'getConnectionStatus', 'disconnect'];\n const missingMethods = requiredMethods.filter(method => \n typeof window.secureBitChat[method] !== 'function'\n );\n \n if (missingMethods.length > 0) {\n this._secureLog('error', '\u274C SECURITY ALERT: API tampering detected, missing methods:', { errorType: missingMethods?.constructor?.name || 'Unknown' });\n return false;\n }\n \n return true;\n } catch (error) {\n this._secureLog('error', '\u274C SECURITY ALERT: API integrity check failed:', { errorType: error?.constructor?.name || 'Unknown' });\n return false;\n }\n }\n // ============================================\n // ADDITIONAL SECURITY METHODS\n // ============================================\n \n /**\n * Simple global exposure check - only at initialization\n */\n _auditGlobalExposure() {\n // Only check once at initialization, no periodic scanning\n this._secureLog('info', '\uD83D\uDD12 Global exposure check completed at initialization');\n return [];\n }\n \n /**\n * No periodic security audits - only at initialization\n */\n _startSecurityAudit() {\n // Only audit once at initialization, no periodic checks\n this._secureLog('info', '\uD83D\uDD12 Security audit completed at initialization - no periodic monitoring');\n }\n \n /**\n * Simple global API protection\n */\n _protectGlobalAPI() {\n if (!window.secureBitChat) {\n this._secureLog('warn', '\u26A0\uFE0F Global API not found during protection setup');\n return;\n }\n\n try {\n // Validate API integrity once\n if (this._validateAPIIntegrityOnce()) {\n this._secureLog('info', '\uD83D\uDD12 Global API protection verified');\n }\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to verify global API protection', { \n errorType: error.constructor.name,\n errorMessage: error.message\n });\n }\n }\n \n /**\n * Validate API integrity once at initialization\n */\n _validateAPIIntegrityOnce() {\n try {\n // Check if API is properly configured\n if (!this._importantMethods || !this._importantMethods.getOwnPropertyDescriptor) {\n // Fallback to direct Object.getOwnPropertyDescriptor\n const descriptor = Object.getOwnPropertyDescriptor(window, 'secureBitChat');\n \n if (!descriptor || descriptor.configurable) {\n throw new Error('secureBitChat must not be reconfigurable!');\n }\n } else {\n const descriptor = this._importantMethods.getOwnPropertyDescriptor(window, 'secureBitChat');\n \n if (!descriptor || descriptor.configurable) {\n throw new Error('secureBitChat must not be reconfigurable!');\n }\n }\n \n this._secureLog('info', '\u2705 API integrity validated');\n return true;\n \n } catch (error) {\n this._secureLog('error', '\u274C API integrity validation failed', {\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n return false;\n }\n }\n \n /**\n * Secure memory wipe for sensitive data\n */\n _secureWipeMemory(data, context = 'unknown') {\n if (!data) return;\n \n try {\n // Different handling for different data types\n if (data instanceof ArrayBuffer) {\n this._secureWipeArrayBuffer(data, context);\n } else if (data instanceof Uint8Array) {\n this._secureWipeUint8Array(data, context);\n } else if (Array.isArray(data)) {\n this._secureWipeArray(data, context);\n } else if (typeof data === 'string') {\n this._secureWipeString(data, context);\n } else if (data instanceof CryptoKey) {\n this._secureWipeCryptoKey(data, context);\n } else if (typeof data === 'object') {\n this._secureWipeObject(data, context);\n }\n \n this._secureMemoryManager.memoryStats.totalCleanups++;\n \n } catch (error) {\n this._secureMemoryManager.memoryStats.failedCleanups++;\n this._secureLog('error', '\u274C Secure memory wipe failed', {\n context: context,\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n }\n }\n \n /**\n * Secure wipe for ArrayBuffer\n */\n _secureWipeArrayBuffer(buffer, context) {\n if (!buffer || buffer.byteLength === 0) return;\n \n try {\n const view = new Uint8Array(buffer);\n \n // Overwrite with random data first\n crypto.getRandomValues(view);\n \n // Overwrite with zeros\n view.fill(0);\n \n // Overwrite with ones\n view.fill(255);\n \n // Final zero overwrite\n view.fill(0);\n \n this._secureLog('debug', '\uD83D\uDD12 ArrayBuffer securely wiped', {\n context: context,\n size: buffer.byteLength\n });\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to wipe ArrayBuffer', {\n context: context,\n errorType: error.constructor.name\n });\n }\n }\n \n /**\n * Secure wipe for Uint8Array\n */\n _secureWipeUint8Array(array, context) {\n if (!array || array.length === 0) return;\n \n try {\n // Overwrite with random data first\n crypto.getRandomValues(array);\n \n // Overwrite with zeros\n array.fill(0);\n \n // Overwrite with ones\n array.fill(255);\n \n // Final zero overwrite\n array.fill(0);\n \n this._secureLog('debug', '\uD83D\uDD12 Uint8Array securely wiped', {\n context: context,\n size: array.length\n });\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to wipe Uint8Array', {\n context: context,\n errorType: error.constructor.name\n });\n }\n }\n \n /**\n * Secure wipe for arrays\n */\n _secureWipeArray(array, context) {\n if (!Array.isArray(array) || array.length === 0) return;\n \n try {\n // Recursively wipe each element\n array.forEach((item, index) => {\n if (item !== null && item !== undefined) {\n this._secureWipeMemory(item, `${context}[${index}]`);\n }\n });\n \n // Fill with nulls\n array.fill(null);\n \n this._secureLog('debug', '\uD83D\uDD12 Array securely wiped', {\n context: context,\n size: array.length\n });\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to wipe array', {\n context: context,\n errorType: error.constructor.name\n });\n }\n }\n \n /**\n * No string wiping - strings are immutable in JS\n */\n _secureWipeString(str, context) {\n // Strings are immutable in JavaScript, no need to wipe\n // Just remove the reference\n this._secureLog('debug', '\uD83D\uDD12 String reference removed (strings are immutable)', {\n context: context,\n length: str ? str.length : 0\n });\n }\n \n /**\n * CryptoKey cleanup - store in WeakMap for proper GC\n */\n _secureWipeCryptoKey(key, context) {\n if (!key || !(key instanceof CryptoKey)) return;\n \n try {\n // Store in WeakMap for proper garbage collection\n if (!this._cryptoKeyStorage) {\n this._cryptoKeyStorage = new WeakMap();\n }\n \n // Store reference for cleanup tracking\n this._cryptoKeyStorage.set(key, {\n context: context,\n timestamp: Date.now(),\n type: key.type\n });\n \n this._secureLog('debug', '\uD83D\uDD12 CryptoKey stored in WeakMap for cleanup', {\n context: context,\n type: key.type\n });\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to store CryptoKey for cleanup', {\n context: context,\n errorType: error.constructor.name\n });\n }\n }\n \n /**\n * Secure wipe for objects\n */\n _secureWipeObject(obj, context) {\n if (!obj || typeof obj !== 'object') return;\n \n try {\n // Recursively wipe all properties\n for (const [key, value] of Object.entries(obj)) {\n if (value !== null && value !== undefined) {\n this._secureWipeMemory(value, `${context}.${key}`);\n }\n // Set property to null\n obj[key] = null;\n }\n \n this._secureLog('debug', '\uD83D\uDD12 Object securely wiped', {\n context: context,\n properties: Object.keys(obj).length\n });\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to wipe object', {\n context: context,\n errorType: error.constructor.name\n });\n }\n }\n \n /**\n * Secure cleanup of cryptographic materials\n */\n _secureCleanupCryptographicMaterials() {\n try {\n // Secure wipe of key pairs\n if (this.ecdhKeyPair) {\n this._secureWipeMemory(this.ecdhKeyPair, 'ecdhKeyPair');\n this.ecdhKeyPair = null;\n }\n \n if (this.ecdsaKeyPair) {\n this._secureWipeMemory(this.ecdsaKeyPair, 'ecdsaKeyPair');\n this.ecdsaKeyPair = null;\n }\n \n // Secure wipe of derived keys\n if (this.encryptionKey) {\n this._secureWipeMemory(this.encryptionKey, 'encryptionKey');\n this.encryptionKey = null;\n }\n \n if (this.macKey) {\n this._secureWipeMemory(this.macKey, 'macKey');\n this.macKey = null;\n }\n \n if (this.metadataKey) {\n this._secureWipeMemory(this.metadataKey, 'metadataKey');\n this.metadataKey = null;\n }\n \n if (this.nestedEncryptionKey) {\n this._secureWipeMemory(this.nestedEncryptionKey, 'nestedEncryptionKey');\n this.nestedEncryptionKey = null;\n }\n \n // Secure wipe of session data\n if (this.sessionSalt) {\n this._secureWipeMemory(this.sessionSalt, 'sessionSalt');\n this.sessionSalt = null;\n }\n \n if (this.sessionId) {\n this._secureWipeMemory(this.sessionId, 'sessionId');\n this.sessionId = null;\n }\n \n if (this.verificationCode) {\n this._secureWipeMemory(this.verificationCode, 'verificationCode');\n this.verificationCode = null;\n }\n \n if (this.peerPublicKey) {\n this._secureWipeMemory(this.peerPublicKey, 'peerPublicKey');\n this.peerPublicKey = null;\n }\n \n if (this.keyFingerprint) {\n this._secureWipeMemory(this.keyFingerprint, 'keyFingerprint');\n this.keyFingerprint = null;\n }\n \n if (this.connectionId) {\n this._secureWipeMemory(this.connectionId, 'connectionId');\n this.connectionId = null;\n }\n \n this._secureLog('info', '\uD83D\uDD12 Cryptographic materials securely cleaned up');\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to cleanup cryptographic materials', {\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n }\n }\n \n /**\n * Force garbage collection if available\n */\n _forceGarbageCollection() {\n try {\n // Try to force garbage collection if available\n if (typeof window.gc === 'function') {\n window.gc();\n this._secureLog('debug', '\uD83D\uDD12 Garbage collection forced');\n } else if (typeof global.gc === 'function') {\n global.gc();\n this._secureLog('debug', '\uD83D\uDD12 Garbage collection forced (global)');\n } else {\n this._secureLog('debug', '\u26A0\uFE0F Garbage collection not available');\n }\n } catch (error) {\n this._secureLog('error', '\u274C Failed to force garbage collection', {\n errorType: error.constructor.name\n });\n }\n }\n \n /**\n * Perform periodic memory cleanup\n */\n _performPeriodicMemoryCleanup() {\n try {\n this._secureMemoryManager.isCleaning = true;\n \n // Clean up any remaining sensitive data\n this._secureCleanupCryptographicMaterials();\n \n // Clean up message queue if it's too large\n if (this.messageQueue && this.messageQueue.length > 100) {\n const excessMessages = this.messageQueue.splice(0, this.messageQueue.length - 50);\n excessMessages.forEach((message, index) => {\n this._secureWipeMemory(message, `periodicCleanup[${index}]`);\n });\n }\n \n // Clean up processed message IDs if too many\n if (this.processedMessageIds && this.processedMessageIds.size > 1000) {\n this.processedMessageIds.clear();\n }\n \n // Force garbage collection\n this._forceGarbageCollection();\n \n this._secureLog('debug', '\uD83D\uDD12 Periodic memory cleanup completed');\n \n } catch (error) {\n this._secureLog('error', '\u274C Error during periodic memory cleanup', {\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n } finally {\n this._secureMemoryManager.isCleaning = false;\n }\n }\n \n /**\n * Create secure error message without information disclosure\n */\n _createSecureErrorMessage(originalError, context = 'unknown') {\n try {\n // Categorize error for appropriate handling\n const category = this._categorizeError(originalError);\n \n // Generate safe error message based on category\n const safeMessage = this._getSafeErrorMessage(category, context);\n \n // Log detailed error internally for debugging\n this._secureLog('error', 'Internal error occurred', {\n category: category,\n context: context,\n errorType: originalError?.constructor?.name || 'Unknown',\n timestamp: Date.now()\n });\n \n // Track error frequency\n this._trackErrorFrequency(category);\n \n return safeMessage;\n \n } catch (error) {\n // Fallback to generic error if error handling fails\n this._secureLog('error', 'Error handling failed', {\n originalError: originalError?.message || 'Unknown',\n handlingError: error.message\n });\n return 'An unexpected error occurred';\n }\n }\n \n /**\n * Categorize error for appropriate handling\n */\n _categorizeError(error) {\n if (!error || !error.message) {\n return this._secureErrorHandler.errorCategories.UNKNOWN;\n }\n \n const message = error.message.toLowerCase();\n \n // Cryptographic errors\n if (message.includes('crypto') || \n message.includes('key') || \n message.includes('encrypt') || \n message.includes('decrypt') ||\n message.includes('sign') ||\n message.includes('verify') ||\n message.includes('ecdh') ||\n message.includes('ecdsa')) {\n return this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC;\n }\n \n // Network errors\n if (message.includes('network') || \n message.includes('connection') || \n message.includes('timeout') ||\n message.includes('webrtc') ||\n message.includes('peer')) {\n return this._secureErrorHandler.errorCategories.NETWORK;\n }\n \n // Validation errors\n if (message.includes('invalid') || \n message.includes('validation') || \n message.includes('format') ||\n message.includes('type')) {\n return this._secureErrorHandler.errorCategories.VALIDATION;\n }\n \n // System errors\n if (message.includes('system') || \n message.includes('internal') || \n message.includes('memory') ||\n message.includes('resource')) {\n return this._secureErrorHandler.errorCategories.SYSTEM;\n }\n \n return this._secureErrorHandler.errorCategories.UNKNOWN;\n }\n \n /**\n * Get safe error message based on category\n */\n _getSafeErrorMessage(category, context) {\n const safeMessages = {\n [this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC]: {\n 'key_generation': 'Security initialization failed',\n 'key_import': 'Security verification failed',\n 'key_derivation': 'Security setup failed',\n 'encryption': 'Message security failed',\n 'decryption': 'Message verification failed',\n 'signature': 'Authentication failed',\n 'default': 'Security operation failed'\n },\n [this._secureErrorHandler.errorCategories.NETWORK]: {\n 'connection': 'Connection failed',\n 'timeout': 'Connection timeout',\n 'peer': 'Peer connection failed',\n 'webrtc': 'Communication failed',\n 'default': 'Network operation failed'\n },\n [this._secureErrorHandler.errorCategories.VALIDATION]: {\n 'format': 'Invalid data format',\n 'type': 'Invalid data type',\n 'structure': 'Invalid data structure',\n 'default': 'Validation failed'\n },\n [this._secureErrorHandler.errorCategories.SYSTEM]: {\n 'memory': 'System resource error',\n 'resource': 'System resource unavailable',\n 'internal': 'Internal system error',\n 'default': 'System operation failed'\n },\n [this._secureErrorHandler.errorCategories.UNKNOWN]: {\n 'default': 'An unexpected error occurred'\n }\n };\n \n const categoryMessages = safeMessages[category] || safeMessages[this._secureErrorHandler.errorCategories.UNKNOWN];\n \n // Determine specific context for more precise message\n let specificContext = 'default';\n if (context.includes('key') || context.includes('crypto')) {\n specificContext = category === this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC ? 'key_generation' : 'default';\n } else if (context.includes('connection') || context.includes('peer')) {\n specificContext = category === this._secureErrorHandler.errorCategories.NETWORK ? 'connection' : 'default';\n } else if (context.includes('validation') || context.includes('format')) {\n specificContext = category === this._secureErrorHandler.errorCategories.VALIDATION ? 'format' : 'default';\n }\n \n return categoryMessages[specificContext] || categoryMessages.default;\n }\n \n /**\n * Track error frequency for security monitoring\n */\n _trackErrorFrequency(category) {\n const now = Date.now();\n \n // Clean old error counts\n if (now - this._secureErrorHandler.lastErrorTime > 60000) { // 1 minute\n this._secureErrorHandler.errorCounts.clear();\n }\n \n // Increment error count\n const currentCount = this._secureErrorHandler.errorCounts.get(category) || 0;\n this._secureErrorHandler.errorCounts.set(category, currentCount + 1);\n this._secureErrorHandler.lastErrorTime = now;\n \n // Check if we're exceeding error threshold\n const totalErrors = Array.from(this._secureErrorHandler.errorCounts.values()).reduce((sum, count) => sum + count, 0);\n \n if (totalErrors > this._secureErrorHandler.errorThreshold) {\n this._secureErrorHandler.isInErrorMode = true;\n this._secureLog('warn', '\u26A0\uFE0F High error frequency detected - entering error mode', {\n totalErrors: totalErrors,\n threshold: this._secureErrorHandler.errorThreshold\n });\n }\n }\n \n /**\n * Throw secure error without information disclosure\n */\n _throwSecureError(originalError, context = 'unknown') {\n const secureMessage = this._createSecureErrorMessage(originalError, context);\n throw new Error(secureMessage);\n }\n \n /**\n * Get error handling statistics\n */\n _getErrorHandlingStats() {\n return {\n errorCounts: Object.fromEntries(this._secureErrorHandler.errorCounts),\n isInErrorMode: this._secureErrorHandler.isInErrorMode,\n lastErrorTime: this._secureErrorHandler.lastErrorTime,\n errorThreshold: this._secureErrorHandler.errorThreshold\n };\n }\n \n /**\n * Reset error handling system\n */\n _resetErrorHandlingSystem() {\n this._secureErrorHandler.errorCounts.clear();\n this._secureErrorHandler.isInErrorMode = false;\n this._secureErrorHandler.lastErrorTime = 0;\n \n this._secureLog('info', '\uD83D\uDD04 Error handling system reset');\n }\n \n /**\n * Get memory management statistics\n */\n _getMemoryManagementStats() {\n return {\n totalCleanups: this._secureMemoryManager.memoryStats.totalCleanups,\n failedCleanups: this._secureMemoryManager.memoryStats.failedCleanups,\n lastCleanup: this._secureMemoryManager.memoryStats.lastCleanup,\n isCleaning: this._secureMemoryManager.isCleaning,\n queueLength: this._secureMemoryManager.cleanupQueue.length\n };\n }\n \n /**\n * Validate API integrity and security\n */\n _validateAPIIntegrity() {\n try {\n // Check if API exists\n if (!window.secureBitChat) {\n this._secureLog('error', '\u274C Global API not found during integrity validation');\n return false;\n }\n \n // Validate required methods exist\n const requiredMethods = ['sendMessage', 'getConnectionStatus', 'getSecurityStatus', 'sendFile', 'disconnect'];\n const missingMethods = requiredMethods.filter(method => \n !window.secureBitChat[method] || typeof window.secureBitChat[method] !== 'function'\n );\n \n if (missingMethods.length > 0) {\n this._secureLog('error', '\u274C Global API integrity validation failed - missing methods', {\n missingMethods: missingMethods\n });\n return false;\n }\n \n // Test method binding integrity\n const testContext = { test: true };\n const boundMethods = requiredMethods.map(method => {\n try {\n return window.secureBitChat[method].bind(testContext);\n } catch (error) {\n return null;\n }\n });\n \n const unboundMethods = boundMethods.filter(method => method === null);\n if (unboundMethods.length > 0) {\n this._secureLog('error', '\u274C Global API integrity validation failed - method binding issues', {\n unboundMethods: unboundMethods.length\n });\n return false;\n }\n \n // Test API immutability\n try {\n const testProp = '_integrity_test_' + Date.now();\n Object.defineProperty(window.secureBitChat, testProp, {\n value: 'test',\n writable: true,\n configurable: true\n });\n \n this._secureLog('error', '\u274C Global API integrity validation failed - API is mutable');\n delete window.secureBitChat[testProp];\n return false;\n \n } catch (immutabilityError) {\n // This is expected - API should be immutable\n this._secureLog('debug', '\u2705 Global API immutability verified');\n }\n \n this._secureLog('info', '\u2705 Global API integrity validation passed');\n return true;\n \n } catch (error) {\n this._secureLog('error', '\u274C Global API integrity validation failed', {\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n return false;\n }\n }\n\n _validateCryptographicSecurity() {\n // Check if basic security features are available\n const criticalFeatures = ['hasRateLimiting'];\n const missingCritical = criticalFeatures.filter(feature => !this.securityFeatures[feature]);\n \n if (missingCritical.length > 0) {\n this._secureLog('error', '\uD83D\uDEA8 CRITICAL: Missing critical rate limiting feature', {\n missing: missingCritical,\n currentFeatures: this.securityFeatures,\n action: 'Rate limiting will be forced enabled'\n });\n\n missingCritical.forEach(feature => {\n this.securityFeatures[feature] = true;\n this._secureLog('warn', `\u26A0\uFE0F Forced enable critical: ${feature} = true`);\n });\n }\n\n // Log current security state\n const availableFeatures = Object.keys(this.securityFeatures).filter(f => this.securityFeatures[f]);\n const encryptionFeatures = ['hasEncryption', 'hasECDH', 'hasECDSA'].filter(f => this.securityFeatures[f]);\n \n this._secureLog('info', '\u2705 Cryptographic security validation passed', {\n criticalFeatures: criticalFeatures.length,\n availableFeatures: availableFeatures.length,\n encryptionFeatures: encryptionFeatures.length,\n totalSecurityFeatures: availableFeatures.length,\n note: 'Encryption features will be enabled after key generation',\n currentState: {\n hasEncryption: this.securityFeatures.hasEncryption,\n hasECDH: this.securityFeatures.hasECDH,\n hasECDSA: this.securityFeatures.hasECDSA,\n hasRateLimiting: this.securityFeatures.hasRateLimiting\n }\n });\n \n return true;\n }\n\n _syncSecurityFeaturesWithTariff() {\n if (!this.sessionManager || !this.sessionManager.isFeatureAllowedForSession) {\n this._secureLog('warn', '\u26A0\uFE0F Session manager not available, using safe default security features');\n\n // Keep existing features, only add new ones\n // Don't override hasEncryption and hasECDH if they're already true\n if (this.securityFeatures.hasEncryption === undefined) {\n this.securityFeatures.hasEncryption = false; // Will be set to true only after key generation\n }\n if (this.securityFeatures.hasECDH === undefined) {\n this.securityFeatures.hasECDH = false; // Will be set to true only after ECDH key generation\n }\n if (this.securityFeatures.hasECDSA === undefined) {\n this.securityFeatures.hasECDSA = false; // Will be set to true only after ECDSA key generation\n }\n if (this.securityFeatures.hasMutualAuth === undefined) {\n this.securityFeatures.hasMutualAuth = false; // Will be set to true only after mutual auth\n }\n if (this.securityFeatures.hasMetadataProtection === undefined) {\n this.securityFeatures.hasMetadataProtection = false;\n }\n if (this.securityFeatures.hasEnhancedReplayProtection === undefined) {\n this.securityFeatures.hasEnhancedReplayProtection = false;\n }\n if (this.securityFeatures.hasNonExtractableKeys === undefined) {\n this.securityFeatures.hasNonExtractableKeys = false;\n }\n if (this.securityFeatures.hasRateLimiting === undefined) {\n this.securityFeatures.hasRateLimiting = true; // Basic rate limiting always available\n }\n if (this.securityFeatures.hasEnhancedValidation === undefined) {\n this.securityFeatures.hasEnhancedValidation = false;\n }\n if (this.securityFeatures.hasPFS === undefined) {\n this.securityFeatures.hasPFS = false;\n }\n if (this.securityFeatures.hasNestedEncryption === undefined) {\n this.securityFeatures.hasNestedEncryption = false;\n }\n if (this.securityFeatures.hasPacketPadding === undefined) {\n this.securityFeatures.hasPacketPadding = false;\n }\n if (this.securityFeatures.hasPacketReordering === undefined) {\n this.securityFeatures.hasPacketReordering = false;\n }\n if (this.securityFeatures.hasAntiFingerprinting === undefined) {\n this.securityFeatures.hasAntiFingerprinting = false;\n }\n if (this.securityFeatures.hasFakeTraffic === undefined) {\n this.securityFeatures.hasFakeTraffic = false;\n }\n if (this.securityFeatures.hasDecoyChannels === undefined) {\n this.securityFeatures.hasDecoyChannels = false;\n }\n if (this.securityFeatures.hasMessageChunking === undefined) {\n this.securityFeatures.hasMessageChunking = false;\n }\n \n this._secureLog('info', '\u2705 Safe default security features applied (features will be enabled as they become available)');\n return;\n }\n\n let sessionType = 'demo'; \n\n if (this.sessionManager.isFeatureAllowedForSession('premium', 'hasFakeTraffic')) {\n sessionType = 'premium';\n } else if (this.sessionManager.isFeatureAllowedForSession('basic', 'hasECDSA')) {\n sessionType = 'basic';\n }\n \n this._secureLog('info', '\uD83D\uDD12 Syncing security features with tariff plan', { sessionType });\n\n const allFeatures = [\n 'hasEncryption', 'hasECDH', 'hasECDSA', 'hasMutualAuth',\n 'hasMetadataProtection', 'hasEnhancedReplayProtection',\n 'hasNonExtractableKeys', 'hasRateLimiting', 'hasEnhancedValidation', 'hasPFS',\n 'hasNestedEncryption', 'hasPacketPadding', 'hasPacketReordering',\n 'hasAntiFingerprinting', 'hasFakeTraffic', 'hasDecoyChannels', 'hasMessageChunking'\n ];\n \n allFeatures.forEach(feature => {\n const isAllowed = this.sessionManager.isFeatureAllowedForSession(sessionType, feature);\n \n if (this.securityFeatures[feature] !== isAllowed) {\n this._secureLog('info', `\uD83D\uDD04 Syncing ${feature}: ${this.securityFeatures[feature]} \u2192 ${isAllowed}`);\n this.securityFeatures[feature] = isAllowed;\n }\n });\n\n if (this.onStatusChange) {\n this.onStatusChange('security_synced', {\n type: 'tariff_sync',\n sessionType: sessionType,\n features: this.securityFeatures,\n message: `Security features synchronized with ${sessionType} tariff plan`\n });\n }\n \n this._secureLog('info', '\u2705 Security features synchronized with tariff plan', {\n sessionType,\n enabledFeatures: Object.keys(this.securityFeatures).filter(f => this.securityFeatures[f]).length,\n totalFeatures: Object.keys(this.securityFeatures).length\n });\n }\n \n /**\n * Emergency shutdown for critical issues\n */\n _emergencyShutdown(reason = 'Security breach') {\n this._secureLog('error', '\u274C EMERGENCY SHUTDOWN: ${reason}');\n \n try {\n // Clear critical data\n this.encryptionKey = null;\n this.macKey = null;\n this.metadataKey = null;\n this.verificationCode = null;\n this.keyFingerprint = null;\n this.connectionId = null;\n \n // Close connections\n if (this.dataChannel) {\n this.dataChannel.close();\n this.dataChannel = null;\n }\n if (this.peerConnection) {\n this.peerConnection.close();\n this.peerConnection = null;\n }\n \n // Clear buffers\n this.messageQueue = [];\n this.processedMessageIds.clear();\n this.packetBuffer.clear();\n \n // Notify UI\n if (this.onStatusChange) {\n this.onStatusChange('security_breach');\n }\n \n this._secureLog('info', '\uD83D\uDD12 Emergency shutdown completed');\n \n } catch (error) {\n this._secureLog('error', '\u274C Error during emergency shutdown:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n }\n _finalizeSecureInitialization() {\n this._startKeySecurityMonitoring();\n \n // Verify API integrity\n if (!this._verifyAPIIntegrity()) {\n this._secureLog('error', '\u274C Security initialization failed');\n return;\n }\n\n this._startSecurityMonitoring();\n \n // Start periodic log cleanup\n setInterval(() => {\n this._cleanupLogs();\n }, 300000);\n \n this._secureLog('info', '\u2705 Secure WebRTC Manager initialization completed');\n this._secureLog('info', '\uD83D\uDD12 Global exposure protection: Monitoring only, no automatic removal');\n }\n /**\n * Start security monitoring\n * @deprecated Use unified scheduler instead\n */\n _startSecurityMonitoring() {\n // All security monitoring moved to unified scheduler\n this._secureLog('info', '\uD83D\uDD27 Security monitoring moved to unified scheduler');\n }\n /**\n * Validates connection readiness for sending data\n * @param {boolean} throwError - whether to throw on not ready\n * @returns {boolean} true if connection is ready\n */\n _validateConnection(throwError = true) {\n const isDataChannelReady = this.dataChannel && this.dataChannel.readyState === 'open';\n const isConnectionVerified = this.isVerified;\n const isValid = isDataChannelReady && isConnectionVerified;\n \n if (!isValid && throwError) {\n if (!isDataChannelReady) {\n throw new Error('Data channel not ready');\n }\n if (!isConnectionVerified) {\n throw new Error('Connection not verified');\n }\n }\n \n return isValid;\n }\n\n /**\n * Hard gate for traffic blocking without verification\n * This method enforces that NO traffic (including system messages and file transfers)\n * can pass through without proper cryptographic verification\n */\n _enforceVerificationGate(operation = 'unknown', throwError = true) {\n if (!this.isVerified) {\n const errorMessage = `SECURITY VIOLATION: ${operation} blocked - connection not cryptographically verified`;\n this._secureLog('error', errorMessage, {\n operation: operation,\n isVerified: this.isVerified,\n hasKeys: !!(this.encryptionKey && this.macKey),\n timestamp: Date.now()\n });\n \n if (throwError) {\n throw new Error(errorMessage);\n }\n return false;\n }\n return true;\n }\n\n /**\n * Safe method to set isVerified only after cryptographic verification\n * This is the ONLY method that should set isVerified = true\n */\n _setVerifiedStatus(verified, verificationMethod = 'unknown', verificationData = null) {\n if (verified) {\n // Validate that we have proper cryptographic verification\n if (!this.encryptionKey || !this.macKey) {\n throw new Error('Cannot set verified=true without encryption keys');\n }\n \n if (!verificationMethod || verificationMethod === 'unknown') {\n throw new Error('Cannot set verified=true without specifying verification method');\n }\n \n // Log the verification for audit trail\n this._secureLog('info', 'Connection verified through cryptographic verification', {\n verificationMethod: verificationMethod,\n hasEncryptionKey: !!this.encryptionKey,\n hasMacKey: !!this.macKey,\n keyFingerprint: this.keyFingerprint,\n timestamp: Date.now(),\n verificationData: verificationData ? 'provided' : 'none'\n });\n }\n \n this.isVerified = verified;\n \n if (verified) {\n this.onStatusChange('connected');\n } else {\n this.onStatusChange('disconnected');\n }\n }\n\n /**\n * Create AAD (Additional Authenticated Data) for file messages\n * This binds file messages to the current session and prevents replay attacks\n */\n _createFileMessageAAD(messageType, messageData = null) {\n // Verify that _createMessageAAD method is available\n if (typeof this._createMessageAAD !== 'function') {\n throw new Error('_createMessageAAD method is not available in _createFileMessageAAD. Manager may not be fully initialized.');\n }\n // Use the unified AAD creation method with file message flag\n return this._createMessageAAD(messageType, messageData, true);\n }\n\n /**\n * Validate AAD for file messages\n * This ensures file messages are bound to the correct session\n */\n _validateFileMessageAAD(aadString, expectedMessageType = null) {\n try {\n const aad = JSON.parse(aadString);\n \n // Validate session binding\n if (aad.sessionId !== (this.currentSession?.sessionId || 'unknown')) {\n throw new Error('AAD sessionId mismatch - possible replay attack');\n }\n \n if (aad.keyFingerprint !== (this.keyFingerprint || 'unknown')) {\n throw new Error('AAD keyFingerprint mismatch - possible key substitution attack');\n }\n \n // Validate message type if specified\n if (expectedMessageType && aad.messageType !== expectedMessageType) {\n throw new Error(`AAD messageType mismatch - expected ${expectedMessageType}, got ${aad.messageType}`);\n }\n \n // Validate timestamp (prevent very old messages)\n const now = Date.now();\n const messageAge = now - aad.timestamp;\n if (messageAge > 300000) { // 5 minutes\n throw new Error('AAD timestamp too old - possible replay attack');\n }\n \n return aad;\n } catch (error) {\n this._secureLog('error', 'AAD validation failed', { error: error.message, aadString });\n throw new Error(`AAD validation failed: ${error.message}`);\n }\n }\n\n /**\n * Extract DTLS fingerprint from SDP\n * This is essential for MITM protection\n */\n _extractDTLSFingerprintFromSDP(sdp) {\n try {\n if (!sdp || typeof sdp !== 'string') {\n throw new Error('Invalid SDP provided');\n }\n\n // Look for a=fingerprint lines in SDP with more flexible regex\n const fingerprintRegex = /a=fingerprint:([a-zA-Z0-9-]+)\\s+([A-Fa-f0-9:]+)/g;\n const fingerprints = [];\n let match;\n\n while ((match = fingerprintRegex.exec(sdp)) !== null) {\n fingerprints.push({\n algorithm: match[1].toLowerCase(),\n fingerprint: match[2].toLowerCase().replace(/:/g, '')\n });\n }\n\n if (fingerprints.length === 0) {\n // Try alternative fingerprint format\n const altFingerprintRegex = /fingerprint\\s*=\\s*([a-zA-Z0-9-]+)\\s+([A-Fa-f0-9:]+)/gi;\n while ((match = altFingerprintRegex.exec(sdp)) !== null) {\n fingerprints.push({\n algorithm: match[1].toLowerCase(),\n fingerprint: match[2].toLowerCase().replace(/:/g, '')\n });\n }\n }\n\n if (fingerprints.length === 0) {\n this._secureLog('warn', 'No DTLS fingerprints found in SDP - this may be normal for some WebRTC implementations', {\n sdpLength: sdp.length,\n sdpPreview: sdp.substring(0, 200) + '...'\n });\n throw new Error('No DTLS fingerprints found in SDP');\n }\n\n // Prefer SHA-256 fingerprints\n const sha256Fingerprint = fingerprints.find(fp => fp.algorithm === 'sha-256');\n if (sha256Fingerprint) {\n return sha256Fingerprint.fingerprint;\n }\n\n // Fallback to first available fingerprint\n return fingerprints[0].fingerprint;\n } catch (error) {\n this._secureLog('error', 'Failed to extract DTLS fingerprint from SDP', { \n error: error.message,\n sdpLength: sdp?.length || 0\n });\n throw new Error(`DTLS fingerprint extraction failed: ${error.message}`);\n }\n }\n\n /**\n * Validate DTLS fingerprint against expected value\n * This prevents MITM attacks by ensuring the remote peer has the expected certificate\n */\n _validateDTLSFingerprint(receivedFingerprint, expectedFingerprint, context = 'unknown') {\n try {\n if (!receivedFingerprint || !expectedFingerprint) {\n throw new Error('Missing fingerprint for validation');\n }\n\n // Normalize fingerprints (remove colons, convert to lowercase)\n const normalizedReceived = receivedFingerprint.toLowerCase().replace(/:/g, '');\n const normalizedExpected = expectedFingerprint.toLowerCase().replace(/:/g, '');\n\n if (normalizedReceived !== normalizedExpected) {\n this._secureLog('error', 'DTLS fingerprint mismatch - possible MITM attack', {\n context: context,\n received: normalizedReceived,\n expected: normalizedExpected,\n timestamp: Date.now()\n });\n \n throw new Error(`DTLS fingerprint mismatch - possible MITM attack in ${context}`);\n }\n\n this._secureLog('info', 'DTLS fingerprint validation successful', {\n context: context,\n fingerprint: normalizedReceived,\n timestamp: Date.now()\n });\n\n return true;\n } catch (error) {\n this._secureLog('error', 'DTLS fingerprint validation failed', { \n error: error.message, \n context: context \n });\n throw error;\n }\n }\n\n /**\n * Compute SAS (Short Authentication String) for MITM protection\n * Uses HKDF with DTLS fingerprints to generate a stable 7-digit verification code\n * @param {ArrayBuffer|Uint8Array} keyMaterialRaw - Shared secret or key fingerprint data\n * @param {string} localFP - Local DTLS fingerprint\n * @param {string} remoteFP - Remote DTLS fingerprint\n * @returns {Promise} 7-digit SAS code\n */\n async _computeSAS(keyMaterialRaw, localFP, remoteFP) {\n try {\n console.log('_computeSAS called with parameters:', {\n keyMaterialRaw: keyMaterialRaw ? `${keyMaterialRaw.constructor.name} (${keyMaterialRaw.length || keyMaterialRaw.byteLength} bytes)` : 'null/undefined',\n localFP: localFP ? `${localFP.substring(0, 20)}...` : 'null/undefined',\n remoteFP: remoteFP ? `${remoteFP.substring(0, 20)}...` : 'null/undefined'\n });\n \n if (!keyMaterialRaw || !localFP || !remoteFP) {\n const missing = [];\n if (!keyMaterialRaw) missing.push('keyMaterialRaw');\n if (!localFP) missing.push('localFP');\n if (!remoteFP) missing.push('remoteFP');\n throw new Error(`Missing required parameters for SAS computation: ${missing.join(', ')}`);\n }\n\n const enc = new TextEncoder();\n\n // \u0421\u043E\u043B\u044C \u0441\u0432\u044F\u0437\u044B\u0432\u0430\u0435\u043C \u0441 \u043E\u0431\u043E\u0438\u043C\u0438 DTLS-fingerprints (\u0432 \u043E\u0442\u0441\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u043C \u043F\u043E\u0440\u044F\u0434\u043A\u0435),\n // \u0447\u0442\u043E\u0431\u044B SAS \u00AB\u043F\u0440\u0438\u0432\u044F\u0437\u0430\u043B\u0441\u044F\u00BB \u043A \u0440\u0435\u0430\u043B\u044C\u043D\u043E\u043C\u0443 \u0442\u0440\u0430\u043D\u0441\u043F\u043E\u0440\u0442\u0443 \u0438 \u0435\u0433\u043E \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u0430\u043C\n const salt = enc.encode(\n 'webrtc-sas|' + [localFP, remoteFP].sort().join('|')\n );\n\n // \u041F\u043E\u0434\u0433\u043E\u0442\u0430\u0432\u043B\u0438\u0432\u0430\u0435\u043C keyMaterialRaw \u0434\u043B\u044F \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F\n let keyBuffer;\n if (keyMaterialRaw instanceof ArrayBuffer) {\n keyBuffer = keyMaterialRaw;\n } else if (keyMaterialRaw instanceof Uint8Array) {\n keyBuffer = keyMaterialRaw.buffer;\n } else if (typeof keyMaterialRaw === 'string') {\n // \u0415\u0441\u043B\u0438 \u044D\u0442\u043E \u0441\u0442\u0440\u043E\u043A\u0430 (\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, keyFingerprint), \u0434\u0435\u043A\u043E\u0434\u0438\u0440\u0443\u0435\u043C \u0435\u0451\n // \u041F\u0440\u0435\u0434\u043F\u043E\u043B\u0430\u0433\u0430\u0435\u043C, \u0447\u0442\u043E \u044D\u0442\u043E hex \u0441\u0442\u0440\u043E\u043A\u0430\n const hexString = keyMaterialRaw.replace(/:/g, '').replace(/\\s/g, '');\n const bytes = new Uint8Array(hexString.length / 2);\n for (let i = 0; i < hexString.length; i += 2) {\n bytes[i / 2] = parseInt(hexString.substr(i, 2), 16);\n }\n keyBuffer = bytes.buffer;\n } else {\n throw new Error('Invalid keyMaterialRaw type');\n }\n\n // \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u043C HKDF(SHA-256) \u0447\u0442\u043E\u0431\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u0441\u0442\u0430\u0431\u0438\u043B\u044C\u043D\u044B\u0435 64 \u0431\u0438\u0442\u0430 \u044D\u043D\u0442\u0440\u043E\u043F\u0438\u0438 \u0434\u043B\u044F \u043A\u043E\u0434\u0430\n const key = await crypto.subtle.importKey(\n 'raw',\n keyBuffer,\n 'HKDF',\n false,\n ['deriveBits']\n );\n\n const info = enc.encode('p2p-sas-v1');\n const bits = await crypto.subtle.deriveBits(\n { name: 'HKDF', hash: 'SHA-256', salt, info },\n key,\n 64 // 64 \u0431\u0438\u0442\u0430 \u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0434\u043B\u044F 6\u20137 \u0437\u043D\u0430\u043A\u043E\u0432\n );\n\n const dv = new DataView(bits);\n // \u0421\u043C\u0435\u0448\u0438\u0432\u0430\u0435\u043C \u043E\u0431\u0430 32-\u0431\u0438\u0442\u043D\u044B\u0445 \u0441\u043B\u043E\u0432\u0430 \u0438 \u043F\u043E\u043B\u0443\u0447\u0430\u0435\u043C 7-\u0437\u043D\u0430\u0447\u043D\u044B\u0439 \u043A\u043E\u0434\n const n = (dv.getUint32(0) ^ dv.getUint32(4)) >>> 0;\n const sasCode = String(n % 10_000_000).padStart(7, '0'); // 7 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432\n\n console.log('\uD83C\uDFAF _computeSAS computed code:', sasCode, '(type:', typeof sasCode, ')');\n\n this._secureLog('info', 'SAS code computed successfully', {\n localFP: localFP.substring(0, 16) + '...',\n remoteFP: remoteFP.substring(0, 16) + '...',\n sasLength: sasCode.length,\n timestamp: Date.now()\n });\n\n return sasCode;\n } catch (error) {\n this._secureLog('error', 'SAS computation failed', {\n error: error.message,\n keyMaterialType: typeof keyMaterialRaw,\n hasLocalFP: !!localFP,\n hasRemoteFP: !!remoteFP,\n timestamp: Date.now()\n });\n throw new Error(`SAS computation failed: ${error.message}`);\n }\n }\n\n /**\n * UTILITY: Decode hex keyFingerprint to Uint8Array for SAS computation\n * @param {string} hexString - Hex encoded keyFingerprint (e.g., \"aa:bb:cc:dd\")\n * @returns {Uint8Array} Decoded bytes\n */\n _decodeKeyFingerprint(hexString) {\n try {\n if (!hexString || typeof hexString !== 'string') {\n throw new Error('Invalid hex string provided');\n }\n\n // Use the utility from EnhancedSecureCryptoUtils\n return window.EnhancedSecureCryptoUtils.hexToUint8Array(hexString);\n } catch (error) {\n this._secureLog('error', 'Key fingerprint decoding failed', {\n error: error.message,\n inputType: typeof hexString,\n inputLength: hexString?.length || 0\n });\n throw new Error(`Key fingerprint decoding failed: ${error.message}`);\n }\n }\n\n /**\n * Emergency key wipe on fingerprint mismatch\n * This ensures no sensitive data remains if MITM is detected\n */\n _emergencyWipeOnFingerprintMismatch(reason = 'DTLS fingerprint mismatch') {\n try {\n this._secureLog('error', '\uD83D\uDEA8 EMERGENCY: Initiating security wipe due to fingerprint mismatch', {\n reason: reason,\n timestamp: Date.now()\n });\n\n // Wipe all cryptographic materials\n this._secureWipeKeys();\n this._secureWipeMemory(this.encryptionKey, 'emergency_wipe');\n this._secureWipeMemory(this.macKey, 'emergency_wipe');\n this._secureWipeMemory(this.metadataKey, 'emergency_wipe');\n \n // Wipe ephemeral keys for PFS\n this._wipeEphemeralKeys();\n \n // Hard wipe old keys for PFS\n this._hardWipeOldKeys();\n\n // Reset verification status\n this.isVerified = null;\n this.verificationCode = null;\n this.keyFingerprint = null;\n this.connectionId = null;\n this.expectedDTLSFingerprint = null;\n\n // Disconnect immediately\n this.disconnect();\n\n // Notify UI about security breach\n this.deliverMessageToUI('\uD83D\uDEA8 SECURITY BREACH: Connection terminated due to fingerprint mismatch. Possible MITM attack detected!', 'system');\n\n } catch (error) {\n this._secureLog('error', 'Failed to perform emergency wipe', { error: error.message });\n }\n }\n\n /**\n * Set expected DTLS fingerprint via out-of-band channel\n * This should be called after receiving the fingerprint through a secure channel\n * (e.g., QR code, voice call, in-person exchange, etc.)\n */\n setExpectedDTLSFingerprint(fingerprint, source = 'out_of_band') {\n try {\n if (!fingerprint || typeof fingerprint !== 'string') {\n throw new Error('Invalid fingerprint provided');\n }\n\n // Normalize fingerprint\n const normalizedFingerprint = fingerprint.toLowerCase().replace(/:/g, '');\n\n // Validate fingerprint format (should be hex string)\n if (!/^[a-f0-9]{40,64}$/.test(normalizedFingerprint)) {\n throw new Error('Invalid fingerprint format - must be hex string');\n }\n\n this.expectedDTLSFingerprint = normalizedFingerprint;\n\n this._secureLog('info', 'Expected DTLS fingerprint set via out-of-band channel', {\n source: source,\n fingerprint: normalizedFingerprint,\n timestamp: Date.now()\n });\n\n this.deliverMessageToUI(`\u2705 DTLS fingerprint set via ${source}. MITM protection enabled.`, 'system');\n\n } catch (error) {\n this._secureLog('error', 'Failed to set expected DTLS fingerprint', { error: error.message });\n throw error;\n }\n }\n\n /**\n * Get current DTLS fingerprint for out-of-band verification\n * This should be shared through a secure channel (QR code, voice, etc.)\n */\n getCurrentDTLSFingerprint() {\n try {\n if (!this.expectedDTLSFingerprint) {\n throw new Error('No DTLS fingerprint available - connection not established');\n }\n\n return this.expectedDTLSFingerprint;\n } catch (error) {\n this._secureLog('error', 'Failed to get current DTLS fingerprint', { error: error.message });\n throw error;\n }\n }\n\n /**\n * DEBUGGING: Temporarily disable strict DTLS validation\n * This should only be used for debugging connection issues\n */\n disableStrictDTLSValidation() {\n this.strictDTLSValidation = false;\n this._secureLog('warn', '\u26A0\uFE0F Strict DTLS validation disabled - security reduced', {\n timestamp: Date.now()\n });\n this.deliverMessageToUI('\u26A0\uFE0F DTLS validation disabled for debugging', 'system');\n }\n\n /**\n * SECURITY: Re-enable strict DTLS validation\n */\n enableStrictDTLSValidation() {\n this.strictDTLSValidation = true;\n this._secureLog('info', '\u2705 Strict DTLS validation re-enabled', {\n timestamp: Date.now()\n });\n this.deliverMessageToUI('\u2705 DTLS validation re-enabled', 'system');\n }\n\n /**\n * Generate ephemeral ECDH keys for Perfect Forward Secrecy\n * This ensures each session has unique, non-persistent keys\n */\n async _generateEphemeralECDHKeys() {\n try {\n this._secureLog('info', '\uD83D\uDD11 Generating ephemeral ECDH keys for PFS', {\n sessionStartTime: this.sessionStartTime,\n timestamp: Date.now()\n });\n\n // Generate new ephemeral ECDH key pair\n const ephemeralKeyPair = await window.EnhancedSecureCryptoUtils.generateECDHKeyPair();\n \n if (!ephemeralKeyPair || !this._validateKeyPairConstantTime(ephemeralKeyPair)) {\n throw new Error('Ephemeral ECDH key pair validation failed');\n }\n\n // Store ephemeral keys with session binding\n const sessionId = this.currentSession?.sessionId || `session_${Date.now()}`;\n this.ephemeralKeyPairs.set(sessionId, {\n keyPair: ephemeralKeyPair,\n timestamp: Date.now(),\n sessionId: sessionId\n });\n\n this._secureLog('info', '\u2705 Ephemeral ECDH keys generated for PFS', {\n sessionId: sessionId,\n timestamp: Date.now()\n });\n\n return ephemeralKeyPair;\n } catch (error) {\n this._secureLog('error', '\u274C Failed to generate ephemeral ECDH keys', { error: error.message });\n throw new Error(`Ephemeral key generation failed: ${error.message}`);\n }\n }\n\n /**\n * Hard wipe old keys for real PFS\n * This prevents retrospective decryption attacks\n */\n _hardWipeOldKeys() {\n try {\n this._secureLog('info', '\uD83E\uDDF9 Performing hard wipe of old keys for PFS', {\n oldKeysCount: this.oldKeys.size,\n timestamp: Date.now()\n });\n\n // Hard wipe all old keys\n for (const [version, keySet] of this.oldKeys.entries()) {\n if (keySet.encryptionKey) {\n this._secureWipeMemory(keySet.encryptionKey, 'pfs_key_wipe');\n }\n if (keySet.macKey) {\n this._secureWipeMemory(keySet.macKey, 'pfs_key_wipe');\n }\n if (keySet.metadataKey) {\n this._secureWipeMemory(keySet.metadataKey, 'pfs_key_wipe');\n }\n \n // Clear references\n keySet.encryptionKey = null;\n keySet.macKey = null;\n keySet.metadataKey = null;\n keySet.keyFingerprint = null;\n }\n\n // Clear the oldKeys map completely\n this.oldKeys.clear();\n\n // Force garbage collection if available\n if (typeof window.gc === 'function') {\n window.gc();\n }\n\n this._secureLog('info', '\u2705 Hard wipe of old keys completed for PFS', {\n timestamp: Date.now()\n });\n\n } catch (error) {\n this._secureLog('error', '\u274C Failed to perform hard wipe of old keys', { error: error.message });\n }\n }\n\n /**\n * Wipe ephemeral keys when session ends\n * This ensures session-specific keys are destroyed\n */\n _wipeEphemeralKeys() {\n try {\n this._secureLog('info', '\uD83E\uDDF9 Wiping ephemeral keys for PFS', {\n ephemeralKeysCount: this.ephemeralKeyPairs.size,\n timestamp: Date.now()\n });\n\n // Wipe all ephemeral key pairs\n for (const [sessionId, keyData] of this.ephemeralKeyPairs.entries()) {\n if (keyData.keyPair?.privateKey) {\n this._secureWipeMemory(keyData.keyPair.privateKey, 'ephemeral_key_wipe');\n }\n if (keyData.keyPair?.publicKey) {\n this._secureWipeMemory(keyData.keyPair.publicKey, 'ephemeral_key_wipe');\n }\n \n // Clear references\n keyData.keyPair = null;\n keyData.timestamp = null;\n keyData.sessionId = null;\n }\n\n // Clear the ephemeral keys map\n this.ephemeralKeyPairs.clear();\n\n // Force garbage collection if available\n if (typeof window.gc === 'function') {\n window.gc();\n }\n\n this._secureLog('info', '\u2705 Ephemeral keys wiped for PFS', {\n timestamp: Date.now()\n });\n\n } catch (error) {\n this._secureLog('error', '\u274C Failed to wipe ephemeral keys', { error: error.message });\n }\n }\n\n /**\n * Encrypt file messages with AAD\n * This ensures file messages are properly authenticated and bound to session\n */\n async _encryptFileMessage(messageData, aad) {\n try {\n if (!this.encryptionKey) {\n throw new Error('No encryption key available for file message');\n }\n\n // Convert message to string if it's an object\n const messageString = typeof messageData === 'string' ? messageData : JSON.stringify(messageData);\n \n // Encrypt with AAD using AES-GCM\n const encryptedData = await window.EnhancedSecureCryptoUtils.encryptDataWithAAD(\n messageString, \n this.encryptionKey, \n aad\n );\n \n // Create encrypted message wrapper\n const encryptedMessage = {\n type: 'encrypted_file_message',\n encryptedData: encryptedData,\n aad: aad,\n timestamp: Date.now(),\n keyFingerprint: this.keyFingerprint\n };\n \n return JSON.stringify(encryptedMessage);\n } catch (error) {\n this._secureLog('error', 'Failed to encrypt file message', { error: error.message });\n throw new Error(`File message encryption failed: ${error.message}`);\n }\n }\n\n /**\n * Decrypt file messages with AAD validation\n * This ensures file messages are properly authenticated and bound to session\n */\n async _decryptFileMessage(encryptedMessageString) {\n try {\n const encryptedMessage = JSON.parse(encryptedMessageString);\n \n if (encryptedMessage.type !== 'encrypted_file_message') {\n throw new Error('Invalid encrypted file message type');\n }\n \n // Validate key fingerprint\n if (encryptedMessage.keyFingerprint !== this.keyFingerprint) {\n throw new Error('Key fingerprint mismatch in encrypted file message');\n }\n \n // Validate AAD with sequence number\n const aad = this._validateMessageAAD(encryptedMessage.aad, 'file_message');\n \n if (!this.encryptionKey) {\n throw new Error('No encryption key available for file message decryption');\n }\n \n // Decrypt with AAD validation\n const decryptedData = await window.EnhancedSecureCryptoUtils.decryptDataWithAAD(\n encryptedMessage.encryptedData,\n this.encryptionKey,\n encryptedMessage.aad\n );\n \n return {\n decryptedData: decryptedData,\n aad: aad\n };\n } catch (error) {\n this._secureLog('error', 'Failed to decrypt file message', { error: error.message });\n throw new Error(`File message decryption failed: ${error.message}`);\n }\n }\n\n /**\n * Validates encryption keys readiness\n * @param {boolean} throwError - whether to throw on not ready\n * @returns {boolean} true if keys are ready\n */\n _validateEncryptionKeys(throwError = true) {\n const hasAllKeys = !!(this.encryptionKey && this.macKey && this.metadataKey);\n \n if (!hasAllKeys && throwError) {\n throw new Error('Encryption keys not initialized');\n }\n \n return hasAllKeys;\n }\n\n /**\n * Checks whether a message is a file-transfer message\n * @param {string|object} data - message payload\n * @returns {boolean} true if it's a file message\n */\n _isFileMessage(data) {\n if (typeof data === 'string') {\n try {\n const parsed = JSON.parse(data);\n return parsed.type && parsed.type.startsWith('file_');\n } catch {\n return false;\n }\n }\n \n if (typeof data === 'object' && data.type) {\n return data.type.startsWith('file_');\n }\n \n return false;\n }\n\n /**\n * Checks whether a message is a system message\n * @param {string|object} data - message payload \n * @returns {boolean} true if it's a system message\n */\n _isSystemMessage(data) {\n const systemTypes = [\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_RESPONSE,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_CONFIRMED,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.PEER_DISCONNECT,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.SECURITY_UPGRADE,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_SIGNAL,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_READY\n ];\n\n if (typeof data === 'string') {\n try {\n const parsed = JSON.parse(data);\n return systemTypes.includes(parsed.type);\n } catch {\n return false;\n }\n }\n \n if (typeof data === 'object' && data.type) {\n return systemTypes.includes(data.type);\n }\n \n return false;\n }\n\n /**\n * Checks whether a message is fake traffic\n * @param {any} data - message payload\n * @returns {boolean} true if it's a fake message\n */\n _isFakeMessage(data) {\n if (typeof data === 'string') {\n try {\n const parsed = JSON.parse(data);\n return parsed.type === EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE || \n parsed.isFakeTraffic === true;\n } catch {\n return false;\n }\n }\n \n if (typeof data === 'object' && data !== null) {\n return data.type === EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE || \n data.isFakeTraffic === true;\n }\n \n return false;\n }\n\n /**\n * Safely executes an operation with error handling\n * @param {Function} operation - operation to execute\n * @param {string} errorMessage - error message to log\n * @param {any} fallback - default value on error\n * @returns {any} operation result or fallback\n */\n _withErrorHandling(operation, errorMessage, fallback = null) {\n try {\n return operation();\n } catch (error) {\n if (this._debugMode) {\n this._secureLog('error', '\u274C ${errorMessage}:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n return fallback;\n }\n }\n\n /**\n * Safely executes an async operation with error handling\n * @param {Function} operation - async operation\n * @param {string} errorMessage - error message to log\n * @param {any} fallback - default value on error\n * @returns {Promise} operation result or fallback\n */\n async _withAsyncErrorHandling(operation, errorMessage, fallback = null) {\n try {\n return await operation();\n } catch (error) {\n if (this._debugMode) {\n this._secureLog('error', '\u274C ${errorMessage}:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n return fallback;\n }\n }\n\n /**\n * Checks rate limits\n * @returns {boolean} true if allowed to proceed\n */\n _checkRateLimit() {\n return window.EnhancedSecureCryptoUtils.rateLimiter.checkConnectionRate(this.rateLimiterId);\n }\n\n /**\n * Extracts message type from data\n * @param {string|object} data - message data\n * @returns {string|null} message type or null\n */\n _getMessageType(data) {\n if (typeof data === 'string') {\n try {\n const parsed = JSON.parse(data);\n return parsed.type || null;\n } catch {\n return null;\n }\n }\n \n if (typeof data === 'object' && data !== null) {\n return data.type || null;\n }\n \n return null;\n }\n\n /**\n * Resets notification flags for a new connection\n */\n _resetNotificationFlags() {\n this.lastSecurityLevelNotification = null;\n this.verificationNotificationSent = false;\n this.verificationInitiationSent = false;\n this.disconnectNotificationSent = false;\n this.reconnectionFailedNotificationSent = false;\n this.peerDisconnectNotificationSent = false;\n this.connectionClosedNotificationSent = false;\n this.fakeTrafficDisabledNotificationSent = false;\n this.advancedFeaturesDisabledNotificationSent = false;\n this.securityUpgradeNotificationSent = false;\n this.lastSecurityUpgradeStage = null;\n this.securityCalculationNotificationSent = false;\n this.lastSecurityCalculationLevel = null;\n }\n\n /**\n * Checks whether a message was filtered out\n * @param {any} result - processing result\n * @returns {boolean} true if filtered\n */\n _isFilteredMessage(result) {\n const filteredResults = Object.values(EnhancedSecureWebRTCManager.FILTERED_RESULTS);\n return filteredResults.includes(result);\n }\n /**\n * Enhanced log cleanup with security checks\n */\n _cleanupLogs() {\n // More aggressive cleanup to prevent data accumulation\n if (this._logCounts.size > 500) {\n this._logCounts.clear();\n this._secureLog('debug', '\uD83E\uDDF9 Log counts cleared due to size limit');\n }\n \n // Clean up old log entries to prevent memory leaks\n const now = Date.now();\n const maxAge = 300000; // 5 minutes\n \n // Check for suspicious log patterns\n let suspiciousCount = 0;\n for (const [key, count] of this._logCounts.entries()) {\n if (count > 10) {\n suspiciousCount++;\n }\n }\n \n // Emergency cleanup if too many suspicious patterns\n if (suspiciousCount > 20) {\n this._logCounts.clear();\n this._secureLog('warn', '\uD83D\uDEA8 Emergency log cleanup due to suspicious patterns');\n }\n \n // Reset security violation counter if system is stable\n if (this._logSecurityViolations > 0 && suspiciousCount < 5) {\n this._logSecurityViolations = Math.max(0, this._logSecurityViolations - 1);\n }\n \n // Clean up old IVs periodically\n if (!this._lastIVCleanupTime || Date.now() - this._lastIVCleanupTime > 300000) { // Every 5 minutes\n this._cleanupOldIVs();\n this._lastIVCleanupTime = Date.now();\n }\n \n // Periodic secure memory cleanup\n if (!this._secureMemoryManager.memoryStats.lastCleanup || \n Date.now() - this._secureMemoryManager.memoryStats.lastCleanup > 600000) { // Every 10 minutes\n this._performPeriodicMemoryCleanup();\n this._secureMemoryManager.memoryStats.lastCleanup = Date.now();\n }\n }\n /**\n * Secure logging stats with sensitive data protection\n */\n _getLoggingStats() {\n // Only return safe statistics\n const stats = {\n isProductionMode: this._isProductionMode,\n debugMode: this._debugMode,\n currentLogLevel: this._currentLogLevel,\n logCountsSize: this._logCounts.size,\n maxLogCount: this._maxLogCount,\n securityViolations: this._logSecurityViolations || 0,\n maxSecurityViolations: this._maxLogSecurityViolations || 3,\n systemStatus: this._currentLogLevel === -1 ? 'DISABLED' : 'ACTIVE'\n };\n \n // Sanitize any potentially sensitive data\n const sanitizedStats = {};\n for (const [key, value] of Object.entries(stats)) {\n if (typeof value === 'string' && this._containsSensitiveContent(value)) {\n sanitizedStats[key] = '[SENSITIVE_DATA_REDACTED]';\n } else {\n sanitizedStats[key] = value;\n }\n }\n \n return sanitizedStats;\n }\n /**\n * Enhanced emergency logging disable with cleanup\n */\n _emergencyDisableLogging() {\n // Immediately disable all logging levels\n this._currentLogLevel = -1;\n \n // Clear all log data to prevent memory leaks\n this._logCounts.clear();\n \n // Clear any cached sensitive data\n if (this._logSecurityViolations) {\n this._logSecurityViolations = 0;\n }\n \n // Override _secureLog to a secure no-op\n this._secureLog = () => {\n // Only allow emergency console errors\n if (arguments[0] === 'error' && this._originalConsole?.error) {\n this._originalConsole.error('\uD83D\uDEA8 SECURITY: Logging system disabled - potential data exposure prevented');\n }\n };\n \n // Store original functions before overriding\n this._originalSanitizeString = this._sanitizeString;\n this._originalSanitizeLogData = this._sanitizeLogData;\n this._originalAuditLogMessage = this._auditLogMessage;\n this._originalContainsSensitiveContent = this._containsSensitiveContent;\n \n // Override all logging methods to prevent bypass\n this._sanitizeString = () => '[LOGGING_DISABLED]';\n this._sanitizeLogData = () => ({ error: 'LOGGING_DISABLED' });\n this._auditLogMessage = () => false;\n this._containsSensitiveContent = () => true; // Block everything\n \n // Force garbage collection if available\n if (typeof window.gc === 'function') {\n try {\n window.gc();\n } catch (e) {\n // Ignore GC errors\n }\n }\n \n // Notify about the emergency shutdown\n this._originalConsole?.error?.('\uD83D\uDEA8 CRITICAL: Secure logging system disabled due to potential data exposure');\n }\n\n /**\n * Reset logging system after emergency shutdown\n * Use this function to restore normal logging functionality\n */\n _resetLoggingSystem() {\n this._secureLog('info', '\uD83D\uDD27 Resetting logging system after emergency shutdown');\n \n // Restore original sanitize functions\n this._sanitizeString = this._originalSanitizeString || ((str) => str);\n this._sanitizeLogData = this._originalSanitizeLogData || ((data) => data);\n this._auditLogMessage = this._originalAuditLogMessage || (() => true);\n this._containsSensitiveContent = this._originalContainsSensitiveContent || (() => false);\n \n // Reset security violation counters\n this._logSecurityViolations = 0;\n \n this._secureLog('info', '\u2705 Logging system reset successfully');\n }\n /**\n * Enhanced audit function for log message security\n */\n _auditLogMessage(message, data) {\n if (!data || typeof data !== 'object') return true;\n \n // Convert to string and check for sensitive content\n const dataString = JSON.stringify(data);\n \n // Check message itself for sensitive content\n if (this._containsSensitiveContent(message)) {\n this._emergencyDisableLogging();\n this._originalConsole?.error?.('\uD83D\uDEA8 SECURITY BREACH: Sensitive content detected in log message');\n return false;\n }\n \n // Check data string for sensitive content\n if (this._containsSensitiveContent(dataString)) {\n this._emergencyDisableLogging();\n this._originalConsole?.error?.('\uD83D\uDEA8 SECURITY BREACH: Sensitive content detected in log data');\n return false;\n }\n \n // Enhanced dangerous pattern detection\n const dangerousPatterns = [\n 'secret', 'token', 'password', 'credential', 'auth',\n 'fingerprint', 'salt', 'signature', 'private_key', 'api_key', 'private',\n 'encryption', 'mac', 'metadata', 'session', 'jwt', 'bearer',\n 'key', 'hash', 'digest', 'nonce', 'iv', 'cipher'\n ];\n \n const dataStringLower = dataString.toLowerCase();\n \n for (const pattern of dangerousPatterns) {\n if (dataStringLower.includes(pattern) && !this._safeFieldsWhitelist.has(pattern)) {\n this._emergencyDisableLogging();\n this._originalConsole?.error?.(`\uD83D\uDEA8 SECURITY BREACH: Dangerous pattern detected in log: ${pattern}`);\n return false;\n }\n }\n \n // Check for high entropy values in data\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === 'string' && this._hasHighEntropy(value)) {\n this._emergencyDisableLogging();\n this._originalConsole?.error?.(`\uD83D\uDEA8 SECURITY BREACH: High entropy value detected in log field: ${key}`);\n return false;\n }\n }\n \n return true;\n }\n\n initializeFileTransfer() {\n try {\n this._secureLog('info', '\uD83D\uDD27 Initializing Enhanced Secure File Transfer system...');\n\n if (this.fileTransferSystem) {\n this._secureLog('info', '\u2705 File transfer system already initialized');\n return;\n }\n \n // Step-by-step readiness check\n const channelReady = !!(this.dataChannel && this.dataChannel.readyState === 'open');\n if (!channelReady) {\n this._secureLog('warn', '\u26A0\uFE0F Data channel not open, deferring file transfer initialization');\n if (this.dataChannel) {\n const initHandler = () => {\n this._secureLog('info', '\uD83D\uDD04 DataChannel opened, initializing file transfer...');\n this.initializeFileTransfer();\n };\n this.dataChannel.addEventListener('open', initHandler, { once: true });\n }\n return;\n }\n\n if (!this.isVerified) {\n this._secureLog('warn', '\u26A0\uFE0F Connection not verified yet, deferring file transfer initialization');\n setTimeout(() => this.initializeFileTransfer(), 500);\n return;\n }\n \n // FIX: Clean up previous system if present\n if (this.fileTransferSystem) {\n this._secureLog('info', '\uD83E\uDDF9 Cleaning up existing file transfer system');\n this.fileTransferSystem.cleanup();\n this.fileTransferSystem = null;\n }\n \n // Ensure encryption keys are present\n if (!this.encryptionKey || !this.macKey) {\n this._secureLog('warn', '\u26A0\uFE0F Encryption keys not ready, deferring file transfer initialization');\n setTimeout(() => this.initializeFileTransfer(), 1000);\n return;\n }\n \n // IMPORTANT: callback order: (onProgress, onComplete, onError, onFileReceived)\n const safeOnComplete = (summary) => {\n // Sender: finalize transfer, no Blob handling\n try {\n this._secureLog('info', '\uD83C\uDFC1 Sender transfer summary', { summary });\n // Optionally forward as progress/UI event\n if (this.onFileProgress) {\n this.onFileProgress({ type: 'complete', ...summary });\n }\n } catch (e) {\n this._secureLog('warn', '\u26A0\uFE0F onComplete handler failed:', { details: e.message });\n }\n };\n\n this.fileTransferSystem = new EnhancedSecureFileTransfer(\n this,\n this.onFileProgress || null,\n safeOnComplete,\n this.onFileError || null,\n this.onFileReceived || null\n );\n \n this._fileTransferActive = true;\n \n this._secureLog('info', '\u2705 Enhanced Secure File Transfer system initialized successfully');\n \n // Verify the system is ready\n const status = this.fileTransferSystem.getSystemStatus();\n this._secureLog('info', '\uD83D\uDD0D File transfer system status after init', { status });\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to initialize file transfer system', { errorType: error.constructor.name });\n this.fileTransferSystem = null;\n this._fileTransferActive = false;\n }\n }\n\n // ============================================\n // ENHANCED SECURITY INITIALIZATION\n // ============================================\n\n async initializeEnhancedSecurity() {\n try {\n // Generate nested encryption key\n await this.generateNestedEncryptionKey();\n \n // Initialize decoy channels\n if (this.decoyChannelConfig.enabled) {\n this.initializeDecoyChannels();\n }\n \n // Start fake traffic generation\n if (this.fakeTrafficConfig.enabled) {\n this.startFakeTrafficGeneration();\n }\n\n } catch (error) {\n this._secureLog('error', '\u274C Failed to initialize enhanced security', { errorType: error.constructor.name });\n }\n }\n \n // Generate fingerprint mask for anti-fingerprinting with enhanced randomization\n generateFingerprintMask() {\n // Enhanced randomization to prevent side-channel attacks\n const cryptoRandom = crypto.getRandomValues(new Uint8Array(128));\n \n const mask = {\n timingOffset: cryptoRandom[0] % 1000 + cryptoRandom[1] % 500, // 0-1500ms\n sizeVariation: (cryptoRandom[2] % 50 + 75) / 100, // 0.75 to 1.25\n noisePattern: Array.from(crypto.getRandomValues(new Uint8Array(64))), // Increased size\n headerVariations: [\n 'X-Client-Version', 'X-Session-ID', 'X-Request-ID', 'X-Timestamp', 'X-Signature',\n 'X-Secure', 'X-Encrypted', 'X-Protected', 'X-Safe', 'X-Anonymous', 'X-Private'\n ],\n noiseIntensity: cryptoRandom[3] % 100 + 50, // 50-150%\n sizeMultiplier: (cryptoRandom[4] % 50 + 75) / 100, // 0.75-1.25\n timingVariation: cryptoRandom[5] % 1000 + 100 // 100-1100ms\n };\n return mask;\n }\n\n // Security configuration for session type\n configureSecurityForSession(sessionType, securityLevel) {\n this._secureLog('info', `\uD83D\uDD27 Configuring security for ${sessionType} session (${securityLevel} level)`);\n \n this.currentSessionType = sessionType;\n this.currentSecurityLevel = securityLevel;\n \n if (window.sessionManager && window.sessionManager.isFeatureAllowedForSession) {\n this.sessionConstraints = {};\n \n Object.keys(this.securityFeatures).forEach(feature => {\n this.sessionConstraints[feature] = window.sessionManager.isFeatureAllowedForSession(sessionType, feature);\n });\n \n this.applySessionConstraints();\n \n this._secureLog('info', `\u2705 Security configured for ${sessionType}`, { constraints: this.sessionConstraints });\n\n if (!this._validateCryptographicSecurity()) {\n this._secureLog('error', '\uD83D\uDEA8 CRITICAL: Cryptographic security validation failed after session configuration');\n\n if (this.onStatusChange) {\n this.onStatusChange('security_breach', {\n type: 'crypto_security_failure',\n sessionType: sessionType,\n message: 'Cryptographic security validation failed after session configuration'\n });\n }\n }\n \n this.notifySecurityLevel();\n \n setTimeout(() => {\n this.calculateAndReportSecurityLevel();\n }, EnhancedSecureWebRTCManager.TIMEOUTS.SECURITY_CALC_DELAY);\n \n } else {\n this._secureLog('warn', '\u26A0\uFE0F Session manager not available, using default security');\n }\n }\n\n // Applying session restrictions\n applySessionConstraints() {\n if (!this.sessionConstraints) return;\n\n // Applying restrictions to security features\n Object.keys(this.sessionConstraints).forEach(feature => {\n const allowed = this.sessionConstraints[feature];\n \n if (!allowed && this.securityFeatures[feature]) {\n this._secureLog('info', `\uD83D\uDD12 Disabling ${feature} for ${this.currentSessionType} session`);\n this.securityFeatures[feature] = false;\n \n // Disabling linked configurations\n switch (feature) {\n case 'hasFakeTraffic':\n this.fakeTrafficConfig.enabled = false;\n this.stopFakeTrafficGeneration();\n break;\n case 'hasDecoyChannels':\n this.decoyChannelConfig.enabled = false;\n this.cleanupDecoyChannels();\n break;\n case 'hasPacketReordering':\n this.reorderingConfig.enabled = false;\n this.packetBuffer.clear();\n break;\n case 'hasAntiFingerprinting':\n this.antiFingerprintingConfig.enabled = false;\n break;\n case 'hasMessageChunking':\n this.chunkingConfig.enabled = false;\n break;\n }\n } else if (allowed && !this.securityFeatures[feature]) {\n this._secureLog('info', `\uD83D\uDD13 Enabling ${feature} for ${this.currentSessionType} session`);\n this.securityFeatures[feature] = true;\n \n // Enable linked configurations\n switch (feature) {\n case 'hasFakeTraffic':\n this.fakeTrafficConfig.enabled = true;\n if (this.isConnected()) {\n this.startFakeTrafficGeneration();\n }\n break;\n case 'hasDecoyChannels':\n this.decoyChannelConfig.enabled = true;\n if (this.isConnected()) {\n this.initializeDecoyChannels();\n }\n break;\n case 'hasPacketReordering':\n this.reorderingConfig.enabled = true;\n break;\n case 'hasAntiFingerprinting':\n this.antiFingerprintingConfig.enabled = true;\n break;\n case 'hasMessageChunking':\n this.chunkingConfig.enabled = true;\n break;\n }\n }\n });\n }\n deliverMessageToUI(message, type = 'received') {\n try {\n // Add debug logs\n this._secureLog('debug', '\uD83D\uDCE4 deliverMessageToUI called', {\n message: message,\n type: type,\n messageType: typeof message,\n hasOnMessage: !!this.onMessage\n });\n \n // Filter out file-transfer and system messages\n if (typeof message === 'object' && message.type) {\n const blockedTypes = [\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_START,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_RESPONSE,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_CHUNK,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.CHUNK_CONFIRMATION,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_COMPLETE,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_ERROR,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_RESPONSE,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_CONFIRMED,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.PEER_DISCONNECT,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_SIGNAL,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_READY,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.SECURITY_UPGRADE\n ];\n if (blockedTypes.includes(message.type)) {\n if (this._debugMode) {\n this._secureLog('warn', `\uD83D\uDED1 Blocked system/file message from UI: ${message.type}`);\n }\n return; // do not show in chat\n }\n }\n\n // Additional check for string messages containing JSON\n if (typeof message === 'string' && message.trim().startsWith('{')) {\n try {\n const parsedMessage = JSON.parse(message);\n if (parsedMessage.type) {\n const blockedTypes = [\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_START,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_RESPONSE,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_CHUNK,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.CHUNK_CONFIRMATION,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_COMPLETE,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_ERROR,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_RESPONSE,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_CONFIRMED,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.PEER_DISCONNECT,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_SIGNAL,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_READY,\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.SECURITY_UPGRADE\n ];\n if (blockedTypes.includes(parsedMessage.type)) {\n if (this._debugMode) {\n this._secureLog('warn', `\uD83D\uDED1 Blocked system/file message from UI (string): ${parsedMessage.type}`);\n }\n return; // do not show in chat\n }\n }\n } catch (parseError) {\n // Not JSON \u2014 fine for plain text messages\n }\n }\n\n if (this.onMessage) {\n this._secureLog('debug', '\uD83D\uDCE4 Calling this.onMessage callback', { message, type });\n this.onMessage(message, type);\n } else {\n this._secureLog('warn', '\u26A0\uFE0F this.onMessage callback is null or undefined');\n }\n } catch (err) {\n this._secureLog('error', '\u274C Failed to deliver message to UI:', { errorType: err?.constructor?.name || 'Unknown' });\n }\n }\n\n\n // Security Level Notification\n notifySecurityLevel() {\n // Avoid duplicate notifications for the same security level\n if (this.lastSecurityLevelNotification === this.currentSecurityLevel) {\n return; // prevent duplication\n }\n \n this.lastSecurityLevelNotification = this.currentSecurityLevel;\n \n const levelMessages = {\n 'basic': '\uD83D\uDD12 Basic Security Active - Demo session with essential protection',\n 'enhanced': '\uD83D\uDD10 Enhanced Security Active - Paid session with advanced protection',\n 'maximum': '\uD83D\uDEE1\uFE0F Maximum Security Active - Premium session with complete protection'\n };\n\n const message = levelMessages[this.currentSecurityLevel] || levelMessages['basic'];\n \n if (this.onMessage) {\n this.deliverMessageToUI(message, 'system');\n }\n\n // Showing details of functions for paid sessions\n if (this.currentSecurityLevel !== 'basic' && this.onMessage) {\n const activeFeatures = Object.entries(this.securityFeatures)\n .filter(([key, value]) => value === true)\n .map(([key]) => key.replace('has', '').replace(/([A-Z])/g, ' $1').trim().toLowerCase())\n .slice(0, 5); \n\n this.deliverMessageToUI(`\uD83D\uDD27 Active: ${activeFeatures.join(', ')}...`, 'system');\n }\n }\n\n // Cleaning decoy channels\n cleanupDecoyChannels() {\n // Stopping decoy traffic\n for (const [channelName, timer] of this.decoyTimers.entries()) {\n clearTimeout(timer);\n }\n this.decoyTimers.clear();\n \n // Closing decoy channels\n for (const [channelName, channel] of this.decoyChannels.entries()) {\n if (channel.readyState === 'open') {\n channel.close();\n }\n }\n this.decoyChannels.clear();\n \n this._secureLog('info', '\uD83E\uDDF9 Decoy channels cleaned up');\n }\n\n // ============================================\n // 1. NESTED ENCRYPTION LAYER\n // ============================================\n\n async generateNestedEncryptionKey() {\n try {\n // Generate additional encryption key for nested encryption\n this.nestedEncryptionKey = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n );\n \n // Generate random IV for nested encryption\n // No need for base IV or counter - each encryption gets fresh random IV\n // This ensures maximum entropy and prevents IV reuse attacks\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to generate nested encryption key:', { errorType: error?.constructor?.name || 'Unknown' });\n throw error;\n }\n }\n\n async applyNestedEncryption(data) {\n if (!this.nestedEncryptionKey || !this.securityFeatures.hasNestedEncryption) {\n return data;\n }\n\n try {\n // Generate cryptographically secure IV with reuse prevention\n const uniqueIV = this._generateSecureIV(\n EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE, \n 'nestedEncryption'\n );\n \n // Encrypt data with nested layer\n const encrypted = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv: uniqueIV },\n this.nestedEncryptionKey,\n data\n );\n \n // Combine IV and encrypted data\n const result = new Uint8Array(EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE + encrypted.byteLength);\n result.set(uniqueIV, 0);\n result.set(new Uint8Array(encrypted), EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE);\n \n this._secureLog('debug', '\u2705 Nested encryption applied with secure IV', {\n ivSize: uniqueIV.length,\n dataSize: data.byteLength,\n encryptedSize: encrypted.byteLength\n });\n \n return result.buffer;\n } catch (error) {\n this._secureLog('error', '\u274C Nested encryption failed:', { \n errorType: error?.constructor?.name || 'Unknown',\n errorMessage: error?.message || 'Unknown error'\n });\n \n // If IV generation failed due to emergency mode, disable nested encryption\n if (error.message.includes('emergency mode')) {\n this.securityFeatures.hasNestedEncryption = false;\n this._secureLog('warn', '\u26A0\uFE0F Nested encryption disabled due to IV emergency mode');\n }\n \n return data; // Fallback to original data\n }\n }\n\n async removeNestedEncryption(data) {\n if (!this.nestedEncryptionKey || !this.securityFeatures.hasNestedEncryption) {\n return data;\n }\n\n // Check that the data is actually encrypted with proper IV size\n if (!(data instanceof ArrayBuffer) || data.byteLength < EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE + 16) {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDCDD Data not encrypted or too short for nested decryption (need IV + minimum encrypted data)');\n }\n return data;\n }\n\n try {\n const dataArray = new Uint8Array(data);\n const iv = dataArray.slice(0, EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE);\n const encryptedData = dataArray.slice(EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE);\n \n // Check that there is data to decrypt\n if (encryptedData.length === 0) {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDCDD No encrypted data found');\n }\n return data;\n }\n \n // Decrypt nested layer\n const decrypted = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: iv },\n this.nestedEncryptionKey,\n encryptedData\n );\n \n return decrypted;\n } catch (error) {\n // FIX: Better error handling\n if (error.name === 'OperationError') {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDCDD Data not encrypted with nested encryption, skipping...');\n }\n } else {\n if (this._debugMode) {\n this._secureLog('warn', '\u26A0\uFE0F Nested decryption failed:', { details: error.message });\n }\n }\n return data; // Fallback to original data\n }\n }\n\n // ============================================\n // 2. PACKET PADDING\n // ============================================\n\n applyPacketPadding(data) {\n if (!this.securityFeatures.hasPacketPadding) {\n return data;\n }\n\n try {\n const originalSize = data.byteLength;\n let paddingSize;\n \n if (this.paddingConfig.useRandomPadding) {\n // Generate random padding size\n paddingSize = Math.floor(Math.random() * \n (this.paddingConfig.maxPadding - this.paddingConfig.minPadding + 1)) + \n this.paddingConfig.minPadding;\n } else {\n // Use fixed padding size\n paddingSize = this.paddingConfig.minPadding;\n }\n \n // Generate random padding data\n const padding = crypto.getRandomValues(new Uint8Array(paddingSize));\n \n // Create padded message\n const paddedData = new Uint8Array(originalSize + paddingSize + 4);\n \n // Add original size (4 bytes)\n const sizeView = new DataView(paddedData.buffer, 0, 4);\n sizeView.setUint32(0, originalSize, false);\n \n // Add original data\n paddedData.set(new Uint8Array(data), 4);\n \n // Add padding\n paddedData.set(padding, 4 + originalSize);\n \n return paddedData.buffer;\n } catch (error) {\n this._secureLog('error', '\u274C Packet padding failed:', { errorType: error?.constructor?.name || 'Unknown' });\n return data; // Fallback to original data\n }\n }\n\n removePacketPadding(data) {\n if (!this.securityFeatures.hasPacketPadding) {\n return data;\n }\n\n try {\n const dataArray = new Uint8Array(data);\n \n // Check for minimum data length (4 bytes for size + minimum 1 byte of data)\n if (dataArray.length < 5) {\n if (this._debugMode) {\n this._secureLog('warn', '\u26A0\uFE0F Data too short for packet padding removal, skipping');\n }\n return data;\n }\n \n // Extract original size (first 4 bytes)\n const sizeView = new DataView(dataArray.buffer, 0, 4);\n const originalSize = sizeView.getUint32(0, false);\n \n // Checking the reasonableness of the size\n if (originalSize <= 0 || originalSize > dataArray.length - 4) {\n if (this._debugMode) {\n this._secureLog('warn', '\u26A0\uFE0F Invalid packet padding size, skipping removal');\n }\n return data;\n }\n \n // Extract original data\n const originalData = dataArray.slice(4, 4 + originalSize);\n \n return originalData.buffer;\n } catch (error) {\n if (this._debugMode) {\n this._secureLog('error', '\u274C Packet padding removal failed:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n return data; // Fallback to original data\n }\n }\n\n // ============================================\n // 3. FAKE TRAFFIC GENERATION\n // ============================================\n\n startFakeTrafficGeneration() {\n if (!this.fakeTrafficConfig.enabled || !this.isConnected()) {\n return;\n }\n\n // Prevent multiple fake traffic generators\n if (this.fakeTrafficTimer) {\n this._secureLog('warn', '\u26A0\uFE0F Fake traffic generation already running');\n return;\n }\n\n const sendFakeMessage = async () => {\n if (!this.isConnected()) {\n this.stopFakeTrafficGeneration();\n return;\n }\n\n try {\n const fakeMessage = this.generateFakeMessage();\n await this.sendFakeMessage(fakeMessage);\n \n // FIX: Increase intervals to reduce load\n const nextInterval = this.fakeTrafficConfig.randomDecoyIntervals ? \n Math.random() * (this.fakeTrafficConfig.maxInterval - this.fakeTrafficConfig.minInterval) + \n this.fakeTrafficConfig.minInterval :\n this.fakeTrafficConfig.minInterval;\n \n // Minimum interval 15 seconds for stability\n const safeInterval = Math.max(nextInterval, EnhancedSecureWebRTCManager.TIMEOUTS.FAKE_TRAFFIC_MIN_INTERVAL);\n \n this.fakeTrafficTimer = setTimeout(sendFakeMessage, safeInterval);\n } catch (error) {\n if (this._debugMode) {\n this._secureLog('error', '\u274C Fake traffic generation failed:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n this.stopFakeTrafficGeneration();\n }\n };\n\n // Start fake traffic generation with longer initial delay\n const initialDelay = Math.random() * this.fakeTrafficConfig.maxInterval + EnhancedSecureWebRTCManager.TIMEOUTS.DECOY_INITIAL_DELAY; // Add 5 seconds minimum\n this.fakeTrafficTimer = setTimeout(sendFakeMessage, initialDelay);\n }\n\n stopFakeTrafficGeneration() {\n if (this.fakeTrafficTimer) {\n clearTimeout(this.fakeTrafficTimer);\n this.fakeTrafficTimer = null;\n }\n }\n\n generateFakeMessage() {\n const pattern = this.fakeTrafficConfig.patterns[\n Math.floor(Math.random() * this.fakeTrafficConfig.patterns.length)\n ];\n \n const size = Math.floor(Math.random() * \n (this.fakeTrafficConfig.maxSize - this.fakeTrafficConfig.minSize + 1)) + \n this.fakeTrafficConfig.minSize;\n \n const fakeData = crypto.getRandomValues(new Uint8Array(size));\n \n return {\n type: EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE, \n pattern: pattern,\n data: Array.from(fakeData).map(b => b.toString(16).padStart(2, '0')).join(''),\n timestamp: Date.now(),\n size: size,\n isFakeTraffic: true, \n source: 'fake_traffic_generator',\n fakeId: crypto.getRandomValues(new Uint32Array(1))[0].toString(36) \n };\n }\n\n // ============================================\n // EMERGENCY SHUT-OFF OF ADVANCED FUNCTIONS\n // ============================================\n\n emergencyDisableAdvancedFeatures() {\n this._secureLog('error', '\uD83D\uDEA8 Emergency disabling advanced security features due to errors');\n \n // Disable problematic functions\n this.securityFeatures.hasNestedEncryption = false;\n this.securityFeatures.hasPacketReordering = false;\n this.securityFeatures.hasAntiFingerprinting = false;\n \n // Disable configurations\n this.reorderingConfig.enabled = false;\n this.antiFingerprintingConfig.enabled = false;\n \n // Clear the buffers\n this.packetBuffer.clear();\n \n // Stopping fake traffic\n this.emergencyDisableFakeTraffic();\n \n this._secureLog('info', '\u2705 Advanced features disabled, keeping basic encryption');\n \n // Check that advanced-features-disabled notification wasn't already sent\n if (!this.advancedFeaturesDisabledNotificationSent) {\n this.advancedFeaturesDisabledNotificationSent = true;\n if (this.onMessage) {\n this.deliverMessageToUI('\uD83D\uDEA8 Advanced security features temporarily disabled due to compatibility issues', 'system');\n }\n }\n }\n\n async sendFakeMessage(fakeMessage) {\n if (!this._validateConnection(false)) {\n return;\n }\n\n try {\n this._secureLog('debug', '\uD83C\uDFAD Sending fake message', {\n hasPattern: !!fakeMessage.pattern,\n sizeRange: fakeMessage.size > 100 ? 'large' : 'small'\n });\n \n const fakeData = JSON.stringify({\n ...fakeMessage,\n type: EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE, \n isFakeTraffic: true, \n timestamp: Date.now()\n });\n \n const fakeBuffer = new TextEncoder().encode(fakeData);\n const encryptedFake = await this.applySecurityLayers(fakeBuffer, true);\n this.dataChannel.send(encryptedFake);\n \n this._secureLog('debug', '\uD83C\uDFAD Fake message sent successfully', {\n pattern: fakeMessage.pattern\n });\n } catch (error) {\n this._secureLog('error', '\u274C Failed to send fake message', {\n error: error.message\n });\n }\n }\n\ncheckFakeTrafficStatus() {\n const status = {\n fakeTrafficEnabled: this.securityFeatures.hasFakeTraffic,\n fakeTrafficConfigEnabled: this.fakeTrafficConfig.enabled,\n timerActive: !!this.fakeTrafficTimer,\n patterns: this.fakeTrafficConfig.patterns,\n intervals: {\n min: this.fakeTrafficConfig.minInterval,\n max: this.fakeTrafficConfig.maxInterval\n }\n };\n \n if (this._debugMode) {\n this._secureLog('info', '\uD83C\uDFAD Fake Traffic Status', { status });\n }\n return status;\n }\nemergencyDisableFakeTraffic() {\n if (this._debugMode) {\n this._secureLog('error', '\uD83D\uDEA8 Emergency disabling fake traffic');\n }\n \n this.securityFeatures.hasFakeTraffic = false;\n this.fakeTrafficConfig.enabled = false;\n this.stopFakeTrafficGeneration();\n \n if (this._debugMode) {\n this._secureLog('info', '\u2705 Fake traffic disabled');\n }\n \n // Check that fake-traffic-disabled notification wasn't already sent\n if (!this.fakeTrafficDisabledNotificationSent) {\n this.fakeTrafficDisabledNotificationSent = true;\n if (this.onMessage) {\n this.deliverMessageToUI('\uD83D\uDEA8 Fake traffic emergency disabled', 'system');\n }\n }\n }\n async _applySecurityLayersWithoutMutex(data, isFakeMessage = false) {\n try {\n let processedData = data;\n \n if (isFakeMessage) {\n if (this.encryptionKey && typeof processedData === 'string') {\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\n }\n return processedData;\n }\n \n // Nested Encryption (if enabled)\n if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey && processedData instanceof ArrayBuffer) {\n processedData = await this.applyNestedEncryption(processedData);\n }\n \n // Packet Reordering (if enabled)\n if (this.securityFeatures.hasPacketReordering && this.reorderingConfig?.enabled && processedData instanceof ArrayBuffer) {\n processedData = this.applyPacketReordering(processedData);\n }\n \n // Packet Padding (if enabled)\n if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) {\n processedData = this.applyPacketPadding(processedData);\n }\n \n // Anti-Fingerprinting (if enabled)\n if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) {\n processedData = this.applyAntiFingerprinting(processedData);\n }\n \n // Final encryption (if keys are present)\n if (this.encryptionKey && typeof processedData === 'string') {\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\n }\n \n return processedData;\n \n } catch (error) {\n this._secureLog('error', '\u274C Error in applySecurityLayersWithoutMutex:', { errorType: error?.constructor?.name || 'Unknown' });\n return data; // Return original data on error\n }\n}\n // ============================================\n // 4. MESSAGE CHUNKING\n // ============================================\n\n async processChunkedMessage(chunkData) {\n try {\n if (!this.chunkingConfig.addChunkHeaders) {\n // No headers, treat as regular message\n return this.processMessage(chunkData);\n }\n\n const chunkArray = new Uint8Array(chunkData);\n if (chunkArray.length < 16) {\n // Too small to be a chunk with header\n return this.processMessage(chunkData);\n }\n\n // Extract chunk header\n const headerView = new DataView(chunkArray.buffer, 0, 16);\n const messageId = headerView.getUint32(0, false);\n const chunkIndex = headerView.getUint32(4, false);\n const totalChunks = headerView.getUint32(8, false);\n const chunkSize = headerView.getUint32(12, false);\n\n // Extract chunk data\n const chunk = chunkArray.slice(16, 16 + chunkSize);\n\n // Store chunk in buffer\n if (!this.chunkQueue[messageId]) {\n this.chunkQueue[messageId] = {\n chunks: new Array(totalChunks),\n received: 0,\n timestamp: Date.now()\n };\n }\n\n const messageBuffer = this.chunkQueue[messageId];\n messageBuffer.chunks[chunkIndex] = chunk;\n messageBuffer.received++;\n\n this._secureLog('debug', `\uD83D\uDCE6 Received chunk ${chunkIndex + 1}/${totalChunks} for message ${messageId}`);\n\n // Check if all chunks received\n if (messageBuffer.received === totalChunks) {\n // Combine all chunks\n const totalSize = messageBuffer.chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combinedData = new Uint8Array(totalSize);\n \n let offset = 0;\n for (const chunk of messageBuffer.chunks) {\n combinedData.set(chunk, offset);\n offset += chunk.length;\n }\n\n // Process complete message\n await this.processMessage(combinedData.buffer);\n \n // Clean up\n delete this.chunkQueue[messageId];\n \n this._secureLog('info', `\uD83D\uDCE6 Chunked message ${messageId} reassembled and processed`);\n }\n } catch (error) {\n this._secureLog('error', '\u274C Chunked message processing failed:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n }\n\n // ============================================\n // 5. DECOY CHANNELS\n // ============================================\n\n initializeDecoyChannels() {\n if (!this.decoyChannelConfig.enabled || !this.peerConnection) {\n return;\n }\n\n // Prevent multiple initializations\n if (this.decoyChannels.size > 0) {\n this._secureLog('warn', '\u26A0\uFE0F Decoy channels already initialized, skipping...');\n return;\n }\n\n try {\n const numDecoyChannels = Math.min(\n this.decoyChannelConfig.maxDecoyChannels,\n this.decoyChannelConfig.decoyChannelNames.length\n );\n\n for (let i = 0; i < numDecoyChannels; i++) {\n const channelName = this.decoyChannelConfig.decoyChannelNames[i];\n const decoyChannel = this.peerConnection.createDataChannel(channelName, {\n ordered: Math.random() > 0.5,\n maxRetransmits: Math.floor(Math.random() * 3)\n });\n\n this.setupDecoyChannel(decoyChannel, channelName);\n this.decoyChannels.set(channelName, decoyChannel);\n }\n\n if (this._debugMode) {\n this._secureLog('info', `\uD83C\uDFAD Initialized ${numDecoyChannels} decoy channels`);\n }\n } catch (error) {\n if (this._debugMode) {\n this._secureLog('error', '\u274C Failed to initialize decoy channels:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n }\n }\n\n setupDecoyChannel(channel, channelName) {\n channel.onopen = () => {\n if (this._debugMode) {\n this._secureLog('debug', `\uD83C\uDFAD Decoy channel \"${channelName}\" opened`);\n }\n this.startDecoyTraffic(channel, channelName);\n };\n\n channel.onmessage = (event) => {\n if (this._debugMode) {\n this._secureLog('debug', `\uD83C\uDFAD Received decoy message on \"${channelName}\": ${event.data?.length || 'undefined'} bytes`);\n }\n };\n\n channel.onclose = () => {\n if (this._debugMode) {\n this._secureLog('debug', `\uD83C\uDFAD Decoy channel \"${channelName}\" closed`);\n }\n this.stopDecoyTraffic(channelName);\n };\n\n channel.onerror = (error) => {\n if (this._debugMode) {\n this._secureLog('error', `\u274C Decoy channel \"${channelName}\" error`, { error: error.message });\n }\n };\n }\n\n startDecoyTraffic(channel, channelName) {\n const sendDecoyData = async () => {\n if (channel.readyState !== 'open') {\n return;\n }\n\n try {\n const decoyData = this.generateDecoyData(channelName);\n channel.send(decoyData);\n \n const interval = this.decoyChannelConfig.randomDecoyIntervals ?\n Math.random() * 15000 + 10000 : \n 20000; \n \n this.decoyTimers.set(channelName, setTimeout(() => sendDecoyData(), interval));\n } catch (error) {\n if (this._debugMode) {\n this._secureLog('error', `\u274C Failed to send decoy data on \"${channelName}\"`, { error: error.message });\n }\n }\n };\n\n const initialDelay = Math.random() * 10000 + 5000; \n this.decoyTimers.set(channelName, setTimeout(() => sendDecoyData(), initialDelay));\n }\n\n stopDecoyTraffic(channelName) {\n const timer = this.decoyTimers.get(channelName);\n if (timer) {\n clearTimeout(timer);\n this.decoyTimers.delete(channelName);\n }\n }\n\n generateDecoyData(channelName) {\n const decoyTypes = {\n 'sync': () => JSON.stringify({\n type: 'sync',\n timestamp: Date.now(),\n sequence: Math.floor(Math.random() * 1000),\n data: Array.from(crypto.getRandomValues(new Uint8Array(32)))\n .map(b => b.toString(16).padStart(2, '0')).join('')\n }),\n 'status': () => JSON.stringify({\n type: 'status',\n status: ['online', 'away', 'busy'][Math.floor(Math.random() * 3)],\n uptime: Math.floor(Math.random() * 3600),\n data: Array.from(crypto.getRandomValues(new Uint8Array(16)))\n .map(b => b.toString(16).padStart(2, '0')).join('')\n }),\n 'heartbeat': () => JSON.stringify({\n type: 'heartbeat',\n timestamp: Date.now(),\n data: Array.from(crypto.getRandomValues(new Uint8Array(24)))\n .map(b => b.toString(16).padStart(2, '0')).join('')\n }),\n 'metrics': () => JSON.stringify({\n type: 'metrics',\n cpu: Math.random() * 100,\n memory: Math.random() * 100,\n network: Math.random() * 1000,\n data: Array.from(crypto.getRandomValues(new Uint8Array(20)))\n .map(b => b.toString(16).padStart(2, '0')).join('')\n }),\n 'debug': () => JSON.stringify({\n type: 'debug',\n level: ['info', 'warn', 'error'][Math.floor(Math.random() * 3)],\n message: 'Debug message',\n data: Array.from(crypto.getRandomValues(new Uint8Array(28)))\n .map(b => b.toString(16).padStart(2, '0')).join('')\n })\n };\n\n return decoyTypes[channelName] ? decoyTypes[channelName]() : \n Array.from(crypto.getRandomValues(new Uint8Array(64)))\n .map(b => b.toString(16).padStart(2, '0')).join('');\n }\n\n // ============================================\n // 6. PACKET REORDERING PROTECTION\n // ============================================\n\n addReorderingHeaders(data) {\n if (!this.reorderingConfig.enabled) {\n return data;\n }\n\n try {\n const dataArray = new Uint8Array(data);\n const headerSize = this.reorderingConfig.useTimestamps ? 12 : 8;\n const header = new ArrayBuffer(headerSize);\n const headerView = new DataView(header);\n\n // Add sequence number\n if (this.reorderingConfig.useSequenceNumbers) {\n headerView.setUint32(0, this.sequenceNumber++, false);\n }\n\n // Add timestamp\n if (this.reorderingConfig.useTimestamps) {\n headerView.setUint32(4, Date.now(), false);\n }\n\n // Add data size\n headerView.setUint32(this.reorderingConfig.useTimestamps ? 8 : 4, dataArray.length, false);\n\n // Combine header and data\n const result = new Uint8Array(headerSize + dataArray.length);\n result.set(new Uint8Array(header), 0);\n result.set(dataArray, headerSize);\n\n return result.buffer;\n } catch (error) {\n this._secureLog('error', '\u274C Failed to add reordering headers:', { errorType: error?.constructor?.name || 'Unknown' });\n return data;\n }\n }\n\n async processReorderedPacket(data) {\n if (!this.reorderingConfig.enabled) {\n return this.processMessage(data);\n }\n\n try {\n const dataArray = new Uint8Array(data);\n const headerSize = this.reorderingConfig.useTimestamps ? 12 : 8;\n\n if (dataArray.length < headerSize) {\n if (this._debugMode) {\n this._secureLog('warn', '\u26A0\uFE0F Data too short for reordering headers, processing directly');\n }\n return this.processMessage(data);\n }\n\n const headerView = new DataView(dataArray.buffer, 0, headerSize);\n let sequence = 0;\n let timestamp = 0;\n let dataSize = 0;\n\n if (this.reorderingConfig.useSequenceNumbers) {\n sequence = headerView.getUint32(0, false);\n }\n\n if (this.reorderingConfig.useTimestamps) {\n timestamp = headerView.getUint32(4, false);\n }\n\n dataSize = headerView.getUint32(this.reorderingConfig.useTimestamps ? 8 : 4, false);\n\n if (dataSize > dataArray.length - headerSize || dataSize <= 0) {\n if (this._debugMode) {\n this._secureLog('warn', '\u26A0\uFE0F Invalid reordered packet data size, processing directly');\n }\n return this.processMessage(data);\n }\n\n const actualData = dataArray.slice(headerSize, headerSize + dataSize);\n\n try {\n const textData = new TextDecoder().decode(actualData);\n const content = JSON.parse(textData);\n if (content.type === 'fake' || content.isFakeTraffic === true) {\n if (this._debugMode) {\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Reordered fake message: ${content.pattern || 'unknown'}`);\n }\n return; \n }\n } catch (e) {\n\n }\n\n this.packetBuffer.set(sequence, {\n data: actualData.buffer,\n timestamp: timestamp || Date.now()\n });\n\n await this.processOrderedPackets();\n\n } catch (error) {\n this._secureLog('error', '\u274C Failed to process reordered packet:', { errorType: error?.constructor?.name || 'Unknown' });\n return this.processMessage(data);\n }\n}\n\n// ============================================\n// IMPROVED PROCESSORDEREDPACKETS with filtering\n// ============================================\n\nasync processOrderedPackets() {\n const now = Date.now();\n const timeout = this.reorderingConfig.reorderTimeout;\n\n while (true) {\n const nextSequence = this.lastProcessedSequence + 1;\n const packet = this.packetBuffer.get(nextSequence);\n\n if (!packet) {\n const oldestPacket = this.findOldestPacket();\n if (oldestPacket && (now - oldestPacket.timestamp) > timeout) {\n this._secureLog('warn', '\u26A0\uFE0F Packet ${oldestPacket.sequence} timed out, processing out of order');\n \n try {\n const textData = new TextDecoder().decode(oldestPacket.data);\n const content = JSON.parse(textData);\n if (content.type === 'fake' || content.isFakeTraffic === true) {\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Timed out fake message: ${content.pattern || 'unknown'}`);\n this.packetBuffer.delete(oldestPacket.sequence);\n this.lastProcessedSequence = oldestPacket.sequence;\n continue; \n }\n } catch (e) {\n }\n \n await this.processMessage(oldestPacket.data);\n this.packetBuffer.delete(oldestPacket.sequence);\n this.lastProcessedSequence = oldestPacket.sequence;\n } else {\n break; \n }\n } else {\n try {\n const textData = new TextDecoder().decode(packet.data);\n const content = JSON.parse(textData);\n if (content.type === 'fake' || content.isFakeTraffic === true) {\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Ordered fake message: ${content.pattern || 'unknown'}`);\n this.packetBuffer.delete(nextSequence);\n this.lastProcessedSequence = nextSequence;\n continue; \n }\n } catch (e) {\n }\n \n await this.processMessage(packet.data);\n this.packetBuffer.delete(nextSequence);\n this.lastProcessedSequence = nextSequence;\n }\n }\n\n this.cleanupOldPackets(now, timeout);\n}\n\n\n findOldestPacket() {\n let oldest = null;\n for (const [sequence, packet] of this.packetBuffer.entries()) {\n if (!oldest || packet.timestamp < oldest.timestamp) {\n oldest = { sequence, ...packet };\n }\n }\n return oldest;\n }\n\n cleanupOldPackets(now, timeout) {\n for (const [sequence, packet] of this.packetBuffer.entries()) {\n if ((now - packet.timestamp) > timeout) {\n this._secureLog('warn', '\u26A0\uFE0F \uD83D\uDDD1\uFE0F Removing timed out packet ${sequence}');\n this.packetBuffer.delete(sequence);\n }\n }\n }\n\n // ============================================\n // 7. ANTI-FINGERPRINTING\n // ============================================\n\n applyAntiFingerprinting(data) {\n if (!this.antiFingerprintingConfig.enabled) {\n return data;\n }\n\n try {\n let processedData = data;\n\n // Add random noise\n if (this.antiFingerprintingConfig.addNoise) {\n processedData = this.addNoise(processedData);\n }\n\n // Randomize sizes\n if (this.antiFingerprintingConfig.randomizeSizes) {\n processedData = this.randomizeSize(processedData);\n }\n\n // Mask patterns\n if (this.antiFingerprintingConfig.maskPatterns) {\n processedData = this.maskPatterns(processedData);\n }\n\n // Add random headers\n if (this.antiFingerprintingConfig.useRandomHeaders) {\n processedData = this.addRandomHeaders(processedData);\n }\n\n return processedData;\n } catch (error) {\n this._secureLog('error', '\u274C Anti-fingerprinting failed:', { errorType: error?.constructor?.name || 'Unknown' });\n return data;\n }\n }\n\n addNoise(data) {\n const dataArray = new Uint8Array(data);\n const noiseSize = Math.floor(Math.random() * 32) + 8; // 8-40 bytes\n const noise = crypto.getRandomValues(new Uint8Array(noiseSize));\n \n const result = new Uint8Array(dataArray.length + noiseSize);\n result.set(dataArray, 0);\n result.set(noise, dataArray.length);\n \n return result.buffer;\n }\n\n randomizeSize(data) {\n const dataArray = new Uint8Array(data);\n const variation = this.fingerprintMask.sizeVariation;\n const targetSize = Math.floor(dataArray.length * variation);\n \n if (targetSize > dataArray.length) {\n // Add padding to increase size\n const padding = crypto.getRandomValues(new Uint8Array(targetSize - dataArray.length));\n const result = new Uint8Array(targetSize);\n result.set(dataArray, 0);\n result.set(padding, dataArray.length);\n return result.buffer;\n } else if (targetSize < dataArray.length) {\n // Truncate to decrease size\n return dataArray.slice(0, targetSize).buffer;\n }\n \n return data;\n }\n\n maskPatterns(data) {\n const dataArray = new Uint8Array(data);\n const result = new Uint8Array(dataArray.length);\n \n // Apply XOR with noise pattern\n for (let i = 0; i < dataArray.length; i++) {\n const noiseByte = this.fingerprintMask.noisePattern[i % this.fingerprintMask.noisePattern.length];\n result[i] = dataArray[i] ^ noiseByte;\n }\n \n return result.buffer;\n }\n\n addRandomHeaders(data) {\n const dataArray = new Uint8Array(data);\n const headerCount = Math.floor(Math.random() * 3) + 1; // 1-3 headers\n let totalHeaderSize = 0;\n \n // Calculate total header size\n for (let i = 0; i < headerCount; i++) {\n totalHeaderSize += 4 + Math.floor(Math.random() * 16) + 4; // size + data + checksum\n }\n \n const result = new Uint8Array(totalHeaderSize + dataArray.length);\n let offset = 0;\n \n // Add random headers\n for (let i = 0; i < headerCount; i++) {\n const headerName = this.fingerprintMask.headerVariations[\n Math.floor(Math.random() * this.fingerprintMask.headerVariations.length)\n ];\n const headerData = crypto.getRandomValues(new Uint8Array(Math.floor(Math.random() * 16) + 4));\n \n // Header structure: [size:4][name:4][data:variable][checksum:4]\n const headerView = new DataView(result.buffer, offset);\n headerView.setUint32(0, headerData.length + 8, false); // Total header size\n headerView.setUint32(4, this.hashString(headerName), false); // Name hash\n \n result.set(headerData, offset + 8);\n \n // Add checksum\n const checksum = this.calculateChecksum(result.slice(offset, offset + 8 + headerData.length));\n const checksumView = new DataView(result.buffer, offset + 8 + headerData.length);\n checksumView.setUint32(0, checksum, false);\n \n offset += 8 + headerData.length + 4;\n }\n \n // Add original data\n result.set(dataArray, offset);\n \n return result.buffer;\n }\n\n hashString(str) {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash;\n }\n return Math.abs(hash);\n }\n\n calculateChecksum(data) {\n let checksum = 0;\n for (let i = 0; i < data.length; i++) {\n checksum = (checksum + data[i]) & 0xFFFFFFFF;\n }\n return checksum;\n }\n\n // ============================================\n // ENHANCED MESSAGE SENDING AND RECEIVING\n // ============================================\n\n async removeSecurityLayers(data) {\n try {\n const status = this.getSecurityStatus();\n if (this._debugMode) {\n this._secureLog('debug', `\uD83D\uDD0D removeSecurityLayers (Stage ${status.stage})`, {\n dataType: typeof data,\n dataLength: data?.length || data?.byteLength || 0,\n activeFeatures: status.activeFeaturesCount\n });\n }\n\n if (!data) {\n this._secureLog('warn', '\u26A0\uFE0F Received empty data');\n return null;\n }\n\n let processedData = data;\n\n // IMPORTANT: Early check for fake messages\n if (typeof data === 'string') {\n try {\n const jsonData = JSON.parse(data);\n \n // PRIORITY ONE: Filtering out fake messages\n if (jsonData.type === 'fake') {\n if (this._debugMode) {\n this._secureLog('debug', `\uD83C\uDFAD Fake message filtered out: ${jsonData.pattern} (size: ${jsonData.size})`);\n }\n return 'FAKE_MESSAGE_FILTERED'; \n }\n \n // System messages \u2014 do NOT return for re-processing\n if (jsonData.type && ['heartbeat', 'verification', 'verification_response', 'peer_disconnect', 'key_rotation_signal', 'key_rotation_ready', 'security_upgrade'].includes(jsonData.type)) {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDD27 System message detected, blocking from chat', { type: jsonData.type });\n }\n return 'SYSTEM_MESSAGE_FILTERED';\n }\n \n // File transfer messages \u2014 do NOT return for display\n if (jsonData.type && ['file_transfer_start', 'file_transfer_response', 'file_chunk', 'chunk_confirmation', 'file_transfer_complete', 'file_transfer_error'].includes(jsonData.type)) {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDCC1 File transfer message detected, blocking from chat', { type: jsonData.type });\n }\n return 'FILE_MESSAGE_FILTERED';\n }\n \n // Regular text messages - extract the actual message text\n if (jsonData.type === 'message') {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDCDD Regular message detected, extracting text', { data: jsonData.data });\n }\n return jsonData.data; // Return the actual message text, not the JSON\n }\n \n // Enhanced messages\n if (jsonData.type === 'enhanced_message' && jsonData.data) {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDD10 Enhanced message detected, decrypting...');\n }\n \n if (!this.encryptionKey || !this.macKey || !this.metadataKey) {\n this._secureLog('error', '\u274C Missing encryption keys');\n return null;\n }\n \n const decryptedResult = await window.EnhancedSecureCryptoUtils.decryptMessage(\n jsonData.data,\n this.encryptionKey,\n this.macKey,\n this.metadataKey\n );\n \n if (this._debugMode) {\n this._secureLog('debug', '\u2705 Enhanced message decrypted, extracting...');\n this._secureLog('debug', '\uD83D\uDD0D decryptedResult', {\n type: typeof decryptedResult,\n hasMessage: !!decryptedResult?.message,\n messageType: typeof decryptedResult?.message,\n messageLength: decryptedResult?.message?.length || 0,\n messageSample: decryptedResult?.message?.substring(0, 50) || 'no message'\n });\n }\n \n // CHECKING FOR FAKE MESSAGES AFTER DECRYPTION\n try {\n const decryptedContent = JSON.parse(decryptedResult.message);\n if (decryptedContent.type === 'fake' || decryptedContent.isFakeTraffic === true) {\n if (this._debugMode) {\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Encrypted fake message: ${decryptedContent.pattern || 'unknown'}`);\n }\n return 'FAKE_MESSAGE_FILTERED';\n }\n } catch (e) {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDCDD Decrypted content is not JSON, treating as plain text message');\n }\n }\n \n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDCE4 Returning decrypted message', { message: decryptedResult.message?.substring(0, 50) });\n }\n return decryptedResult.message;\n }\n \n // Regular messages\n if (jsonData.type === 'message' && jsonData.data) {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDCDD Regular message detected, extracting data');\n }\n return jsonData.data; // Return the actual message text\n }\n \n // If it's a regular message with type 'message', let it continue processing\n if (jsonData.type === 'message') {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDCDD Regular message detected, returning for display');\n }\n return data; // Return the original JSON string for processing\n }\n \n // If it's not a special type, return the original data for display\n if (!jsonData.type || (jsonData.type !== 'fake' && !['heartbeat', 'verification', 'verification_response', 'peer_disconnect', 'key_rotation_signal', 'key_rotation_ready', 'enhanced_message', 'security_upgrade', 'file_transfer_start', 'file_transfer_response', 'file_chunk', 'chunk_confirmation', 'file_transfer_complete', 'file_transfer_error'].includes(jsonData.type))) {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDCDD Regular message detected, returning for display');\n }\n return data;\n }\n } catch (e) {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDCC4 Not JSON, processing as raw data');\n }\n // If it's not JSON, it might be a plain text message - return as-is\n return data;\n }\n }\n\n // Standard Decryption\n if (this.encryptionKey && typeof processedData === 'string' && processedData.length > 50) {\n try {\n const base64Regex = /^[A-Za-z0-9+/=]+$/;\n if (base64Regex.test(processedData.trim())) {\n if (this._debugMode) {\n this._secureLog('debug', '\uD83D\uDD13 Applying standard decryption...');\n }\n processedData = await window.EnhancedSecureCryptoUtils.decryptData(processedData, this.encryptionKey);\n if (this._debugMode) {\n this._secureLog('debug', '\u2705 Standard decryption successful');\n }\n \n // CHECKING FOR FAKE MESSAGES AFTER LEGACY DECRYPTION\n if (typeof processedData === 'string') {\n try {\n const legacyContent = JSON.parse(processedData);\n if (legacyContent.type === 'fake' || legacyContent.isFakeTraffic === true) {\n if (this._debugMode) {\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Legacy fake message: ${legacyContent.pattern || 'unknown'}`);\n }\n return 'FAKE_MESSAGE_FILTERED';\n }\n } catch (e) {\n \n }\n processedData = new TextEncoder().encode(processedData).buffer;\n }\n }\n } catch (error) {\n if (this._debugMode) {\n this._secureLog('warn', '\u26A0\uFE0F Standard decryption failed:', { details: error.message });\n }\n return data; \n }\n }\n\n if (this.securityFeatures.hasNestedEncryption && \n this.nestedEncryptionKey && \n processedData instanceof ArrayBuffer &&\n processedData.byteLength > 12) { \n \n try {\n processedData = await this.removeNestedEncryption(processedData);\n \n if (processedData instanceof ArrayBuffer) {\n try {\n const textData = new TextDecoder().decode(processedData);\n const nestedContent = JSON.parse(textData);\n if (nestedContent.type === 'fake' || nestedContent.isFakeTraffic === true) {\n if (this._debugMode) {\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Nested fake message: ${nestedContent.pattern || 'unknown'}`);\n }\n return 'FAKE_MESSAGE_FILTERED';\n }\n } catch (e) {\n \n }\n }\n } catch (error) {\n if (this._debugMode) {\n this._secureLog('warn', '\u26A0\uFE0F Nested decryption failed - skipping this layer:', { details: error.message });\n }\n }\n }\n\n if (this.securityFeatures.hasPacketReordering && \n this.reorderingConfig.enabled && \n processedData instanceof ArrayBuffer) {\n try {\n const headerSize = this.reorderingConfig.useTimestamps ? 12 : 8;\n if (processedData.byteLength > headerSize) {\n return await this.processReorderedPacket(processedData);\n }\n } catch (error) {\n if (this._debugMode) {\n this._secureLog('warn', '\u26A0\uFE0F Reordering processing failed - using direct processing:', { details: error.message });\n }\n }\n }\n\n // Packet Padding Removal\n if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) {\n try {\n processedData = this.removePacketPadding(processedData);\n } catch (error) {\n if (this._debugMode) {\n this._secureLog('warn', '\u26A0\uFE0F Padding removal failed:', { details: error.message });\n }\n }\n }\n\n // Anti-Fingerprinting Removal\n if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) {\n try {\n processedData = this.removeAntiFingerprinting(processedData);\n } catch (error) {\n if (this._debugMode) {\n this._secureLog('warn', '\u26A0\uFE0F Anti-fingerprinting removal failed:', { details: error.message });\n }\n }\n }\n\n // Final transformation\n if (processedData instanceof ArrayBuffer) {\n processedData = new TextDecoder().decode(processedData);\n }\n\n if (typeof processedData === 'string') {\n try {\n const finalContent = JSON.parse(processedData);\n if (finalContent.type === 'fake' || finalContent.isFakeTraffic === true) {\n if (this._debugMode) {\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Final check fake message: ${finalContent.pattern || 'unknown'}`);\n }\n return 'FAKE_MESSAGE_FILTERED';\n }\n } catch (e) {\n }\n }\n\n return processedData;\n\n } catch (error) {\n this._secureLog('error', '\u274C Critical error in removeSecurityLayers:', { errorType: error?.constructor?.name || 'Unknown' });\n return data;\n }\n}\n\n removeAntiFingerprinting(data) {\n // This is a simplified version - in practice, you'd need to reverse all operations\n // For now, we'll just return the data as-is since the operations are mostly additive\n return data;\n }\n\n async applySecurityLayers(data, isFakeMessage = false) {\n try {\n let processedData = data;\n \n if (isFakeMessage) {\n if (this.encryptionKey && typeof processedData === 'string') {\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\n }\n return processedData;\n }\n \n if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey && processedData instanceof ArrayBuffer) {\n processedData = await this.applyNestedEncryption(processedData);\n }\n \n if (this.securityFeatures.hasPacketReordering && this.reorderingConfig?.enabled && processedData instanceof ArrayBuffer) {\n processedData = this.applyPacketReordering(processedData);\n }\n \n if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) {\n processedData = this.applyPacketPadding(processedData);\n }\n \n if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) {\n processedData = this.applyAntiFingerprinting(processedData);\n }\n \n if (this.encryptionKey && typeof processedData === 'string') {\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\n }\n \n return processedData;\n \n } catch (error) {\n this._secureLog('error', '\u274C Error in applySecurityLayers:', { errorType: error?.constructor?.name || 'Unknown' });\n return data;\n }\n }\n\n async sendMessage(data) {\n // Comprehensive input validation\n const validation = this._validateInputData(data, 'sendMessage');\n if (!validation.isValid) {\n const errorMessage = `Input validation failed: ${validation.errors.join(', ')}`;\n this._secureLog('error', '\u274C Input validation failed in sendMessage', {\n errors: validation.errors,\n dataType: typeof data,\n dataLength: data?.length || data?.byteLength || 0\n });\n throw new Error(errorMessage);\n }\n\n // Rate limiting check\n if (!this._checkRateLimit('sendMessage')) {\n throw new Error('Rate limit exceeded for message sending');\n }\n\n // Enforce verification gate\n this._enforceVerificationGate('sendMessage');\n\n // Connection validation\n if (!this.dataChannel || this.dataChannel.readyState !== 'open') {\n throw new Error('Data channel not ready');\n }\n\n try {\n this._secureLog('debug', 'sendMessage called', {\n hasDataChannel: !!this.dataChannel,\n dataChannelReady: this.dataChannel?.readyState === 'open',\n isInitiator: this.isInitiator,\n isVerified: this.isVerified,\n connectionReady: this.peerConnection?.connectionState === 'connected'\n });\n\n this._secureLog('debug', '\uD83D\uDD0D sendMessage DEBUG', {\n dataType: typeof validation.sanitizedData,\n isString: typeof validation.sanitizedData === 'string',\n isArrayBuffer: validation.sanitizedData instanceof ArrayBuffer,\n dataLength: validation.sanitizedData?.length || validation.sanitizedData?.byteLength || 0,\n });\n\n // CRITICAL SECURITY FIX: File messages MUST be encrypted\n // No more bypassing encryption for file_* messages\n if (typeof validation.sanitizedData === 'string') {\n try {\n const parsed = JSON.parse(validation.sanitizedData);\n \n if (parsed.type && parsed.type.startsWith('file_')) {\n this._secureLog('debug', '\uD83D\uDCC1 File message detected - applying full encryption with AAD', { type: parsed.type });\n \n // Create AAD for file message\n const aad = this._createFileMessageAAD(parsed.type, parsed.data);\n \n // Encrypt file message with AAD\n const encryptedData = await this._encryptFileMessage(validation.sanitizedData, aad);\n \n this.dataChannel.send(encryptedData);\n return true;\n }\n } catch (jsonError) {\n // Not JSON \u2014 continue normal handling\n }\n }\n\n // For regular text messages, send via secure path with AAD\n if (typeof validation.sanitizedData === 'string') {\n // Verify that _createMessageAAD method is available\n if (typeof this._createMessageAAD !== 'function') {\n throw new Error('_createMessageAAD method is not available. Manager may not be fully initialized.');\n }\n \n // Create AAD with sequence number for anti-replay protection\n const aad = this._createMessageAAD('message', { content: validation.sanitizedData });\n \n return await this.sendSecureMessage({ \n type: 'message', \n data: validation.sanitizedData, \n timestamp: Date.now(),\n aad: aad // Include AAD for sequence number validation\n });\n }\n\n // For binary data, apply security layers with a limited mutex\n this._secureLog('debug', '\uD83D\uDD10 Applying security layers to non-string data');\n const securedData = await this._applySecurityLayersWithLimitedMutex(validation.sanitizedData, false);\n this.dataChannel.send(securedData);\n \n return true;\n } catch (error) {\n this._secureLog('error', '\u274C Failed to send message', { \n error: error.message,\n errorType: error.constructor.name\n });\n throw error;\n }\n }\n\n // FIX: New method applying security layers with limited mutex use\n async _applySecurityLayersWithLimitedMutex(data, isFakeMessage = false) {\n // Use mutex ONLY for cryptographic operations\n return this._withMutex('cryptoOperation', async (operationId) => {\n try {\n let processedData = data;\n \n if (isFakeMessage) {\n if (this.encryptionKey && typeof processedData === 'string') {\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\n }\n return processedData;\n }\n \n if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey && processedData instanceof ArrayBuffer) {\n processedData = await this.applyNestedEncryption(processedData);\n }\n \n if (this.securityFeatures.hasPacketReordering && this.reorderingConfig?.enabled && processedData instanceof ArrayBuffer) {\n processedData = this.applyPacketReordering(processedData);\n }\n \n if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) {\n processedData = this.applyPacketPadding(processedData);\n }\n \n if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) {\n processedData = this.applyAntiFingerprinting(processedData);\n }\n \n if (this.encryptionKey && typeof processedData === 'string') {\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\n }\n \n return processedData;\n \n } catch (error) {\n this._secureLog('error', '\u274C Error in applySecurityLayers:', { errorType: error?.constructor?.name || 'Unknown' });\n return data;\n }\n }, 3000); // Short timeout for crypto operations\n}\n\n async sendSystemMessage(messageData) {\n // Block system messages without verification\n // Exception: Allow verification-related system messages\n const isVerificationMessage = messageData.type === 'verification_request' || \n messageData.type === 'verification_response' ||\n messageData.type === 'verification_required';\n \n if (!isVerificationMessage) {\n this._enforceVerificationGate('sendSystemMessage', false);\n }\n \n if (!this.dataChannel || this.dataChannel.readyState !== 'open') {\n this._secureLog('warn', '\u26A0\uFE0F Cannot send system message - data channel not ready');\n return false;\n }\n\n try {\n const systemMessage = JSON.stringify({\n type: messageData.type,\n data: messageData,\n timestamp: Date.now()\n });\n\n this._secureLog('debug', '\uD83D\uDD27 Sending system message', { type: messageData.type });\n this.dataChannel.send(systemMessage);\n return true;\n } catch (error) {\n this._secureLog('error', '\u274C Failed to send system message:', { errorType: error?.constructor?.name || 'Unknown' });\n return false;\n }\n }\n\n // FIX 1: Simplified mutex system for message processing\nasync processMessage(data) {\n try {\n this._secureLog('debug', '\uFFFD\uFFFD Processing message', {\n dataType: typeof data,\n isArrayBuffer: data instanceof ArrayBuffer,\n hasData: !!(data?.length || data?.byteLength)\n });\n \n // CRITICAL: Early check for file messages WITHOUT mutex\n if (typeof data === 'string') {\n try {\n const parsed = JSON.parse(data);\n\n // ============================================\n // FILE MESSAGES \u2014 PRIORITY 1 (WITHOUT MUTEX)\n // ============================================\n \n const fileMessageTypes = [\n 'file_transfer_start',\n 'file_transfer_response',\n 'file_chunk', \n 'chunk_confirmation',\n 'file_transfer_complete',\n 'file_transfer_error'\n ];\n\n // CRITICAL SECURITY FIX: Check for encrypted file messages first\n if (parsed.type === 'encrypted_file_message') {\n this._secureLog('debug', '\uD83D\uDCC1 Encrypted file message detected in processMessage');\n \n try {\n // Decrypt and validate file message\n const { decryptedData, aad } = await this._decryptFileMessage(data);\n \n // Parse decrypted data\n const decryptedParsed = JSON.parse(decryptedData);\n \n this._secureLog('debug', '\uD83D\uDCC1 File message decrypted successfully', { \n type: decryptedParsed.type,\n aadMessageType: aad.messageType \n });\n \n // Process decrypted file message\n if (this.fileTransferSystem && typeof this.fileTransferSystem.handleFileMessage === 'function') {\n await this.fileTransferSystem.handleFileMessage(decryptedParsed);\n return;\n }\n } catch (error) {\n this._secureLog('error', '\u274C Failed to decrypt file message', { error: error.message });\n return; // Drop invalid file message\n }\n }\n \n // Legacy unencrypted file messages - should not happen in secure mode\n if (parsed.type && fileMessageTypes.includes(parsed.type)) {\n this._secureLog('warn', '\u26A0\uFE0F Unencrypted file message detected - this should not happen in secure mode', { type: parsed.type });\n \n // Drop unencrypted file messages for security\n this._secureLog('error', '\u274C Dropping unencrypted file message for security', { type: parsed.type });\n return;\n }\n \n // ============================================\n // ENHANCED MESSAGES WITH AAD VALIDATION (WITHOUT MUTEX)\n // ============================================\n \n if (parsed.type === 'enhanced_message') {\n this._secureLog('debug', '\uD83D\uDD10 Enhanced message detected in processMessage');\n \n try {\n // Decrypt enhanced message\n const decryptedData = await window.EnhancedSecureCryptoUtils.decryptMessage(\n parsed.data,\n this.encryptionKey,\n this.macKey,\n this.metadataKey\n );\n \n // Parse decrypted data\n const decryptedParsed = JSON.parse(decryptedData.data);\n \n // Validate AAD with sequence number\n if (decryptedData.metadata && decryptedData.metadata.sequenceNumber !== undefined) {\n if (!this._validateIncomingSequenceNumber(decryptedData.metadata.sequenceNumber, 'enhanced_message')) {\n this._secureLog('warn', '\u26A0\uFE0F Enhanced message sequence number validation failed - possible replay attack', {\n received: decryptedData.metadata.sequenceNumber,\n expected: this.expectedSequenceNumber\n });\n return; // Drop message with invalid sequence number\n }\n }\n \n // Process decrypted message\n if (decryptedParsed.type === 'message' && this.onMessage && decryptedParsed.data) {\n this.deliverMessageToUI(decryptedParsed.data, 'received');\n }\n \n return;\n } catch (error) {\n this._secureLog('error', '\u274C Failed to decrypt enhanced message', { error: error.message });\n return; // Drop invalid enhanced message\n }\n }\n \n // ============================================\n // REGULAR USER MESSAGES (WITHOUT MUTEX)\n // ============================================\n \n if (parsed.type === 'message') {\n this._secureLog('debug', '\uD83D\uDCDD Regular user message detected in processMessage');\n if (this.onMessage && parsed.data) {\n this.deliverMessageToUI(parsed.data, 'received');\n }\n return;\n }\n \n // ============================================\n // SYSTEM MESSAGES (WITHOUT MUTEX)\n // ============================================\n \n if (parsed.type && ['heartbeat', 'verification', 'verification_response', 'verification_confirmed', 'verification_both_confirmed', 'peer_disconnect', 'security_upgrade'].includes(parsed.type)) {\n this.handleSystemMessage(parsed);\n return;\n }\n \n // ============================================\n // FAKE MESSAGES (WITHOUT MUTEX)\n // ============================================\n \n if (parsed.type === 'fake') {\n this._secureLog('warn', '\uD83C\uDFAD Fake message blocked in processMessage', { pattern: parsed.pattern });\n return;\n }\n \n } catch (jsonError) {\n // Not JSON \u2014 treat as text WITHOUT mutex\n if (this.onMessage) {\n this.deliverMessageToUI(data, 'received');\n }\n return;\n }\n }\n\n // ============================================\n // ENCRYPTED DATA PROCESSING (WITH MUTEX ONLY FOR CRYPTO)\n // ============================================\n \n // If here \u2014 apply security layers with limited mutex\n const originalData = await this._processEncryptedDataWithLimitedMutex(data);\n\n // Check processing result\n if (originalData === 'FAKE_MESSAGE_FILTERED' || \n originalData === 'FILE_MESSAGE_FILTERED' || \n originalData === 'SYSTEM_MESSAGE_FILTERED') {\n return;\n }\n \n if (!originalData) {\n this._secureLog('warn', '\u26A0\uFE0F No data returned from removeSecurityLayers');\n return;\n }\n\n // Handle result after removeSecurityLayers\n let messageText;\n \n if (typeof originalData === 'string') {\n try {\n const message = JSON.parse(originalData);\n \n // SECOND CHECK FOR FILE MESSAGES AFTER DECRYPTION\n if (message.type && fileMessageTypes.includes(message.type)) {\n this._secureLog('debug', '\uD83D\uDCC1 File message detected after decryption', { type: message.type });\n if (this.fileTransferSystem) {\n await this.fileTransferSystem.handleFileMessage(message);\n }\n return;\n }\n \n if (message.type && ['heartbeat', 'verification', 'verification_response', 'verification_confirmed', 'verification_both_confirmed', 'peer_disconnect', 'security_upgrade'].includes(message.type)) {\n this.handleSystemMessage(message);\n return;\n }\n \n if (message.type === 'fake') {\n this._secureLog('warn', `\uD83C\uDFAD Post-decryption fake message blocked: ${message.pattern}`);\n return;\n }\n \n // Regular messages\n if (message.type === 'message' && message.data) {\n messageText = message.data;\n } else {\n messageText = originalData;\n }\n } catch (e) {\n messageText = originalData;\n }\n } else if (originalData instanceof ArrayBuffer) {\n messageText = new TextDecoder().decode(originalData);\n } else if (originalData && typeof originalData === 'object' && originalData.message) {\n messageText = originalData.message;\n } else {\n this._secureLog('warn', '\u26A0\uFE0F Unexpected data type after processing:', { details: typeof originalData });\n return;\n }\n\n // Final check for fake and file messages\n if (messageText && messageText.trim().startsWith('{')) {\n try {\n const finalCheck = JSON.parse(messageText);\n if (finalCheck.type === 'fake') {\n this._secureLog('warn', `\uD83C\uDFAD Final fake message check blocked: ${finalCheck.pattern}`);\n return;\n }\n \n // Additional check for file and system messages\n const blockedTypes = [\n 'file_transfer_start', 'file_transfer_response', 'file_chunk', \n 'chunk_confirmation', 'file_transfer_complete', 'file_transfer_error',\n 'heartbeat', 'verification', 'verification_response', \n 'peer_disconnect', 'key_rotation_signal', 'key_rotation_ready', 'security_upgrade'\n ];\n \n if (finalCheck.type && blockedTypes.includes(finalCheck.type)) {\n this._secureLog('warn', `\uD83D\uDCC1 Final system/file message check blocked: ${finalCheck.type}`);\n return;\n }\n } catch (e) {\n // Not JSON \u2014 fine for plain text\n }\n }\n\n // Deliver message to the UI\n if (this.onMessage && messageText) {\n this._secureLog('debug', '\uD83D\uDCE4 Calling message handler with', { message: messageText.substring(0, 100) });\n this.deliverMessageToUI(messageText, 'received');\n }\n\n } catch (error) {\n this._secureLog('error', '\u274C Failed to process message:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n}\n\n // FIX: New method with limited mutex when processing encrypted data\n async _processEncryptedDataWithLimitedMutex(data) {\n // Use mutex ONLY for cryptographic operations\n return this._withMutex('cryptoOperation', async (operationId) => {\n this._secureLog('debug', '\uD83D\uDD10 Processing encrypted data with limited mutex', {\n operationId: operationId,\n dataType: typeof data\n });\n \n try {\n // Apply security layers\n const originalData = await this.removeSecurityLayers(data);\n return originalData;\n \n } catch (error) {\n this._secureLog('error', '\u274C Error processing encrypted data', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n return data; // Return original data on error\n }\n }, 2000); // Short timeout for crypto operations\n }\n\n notifySecurityUpdate() {\n try {\n this._secureLog('debug', '\uD83D\uDD12 Notifying about security level update', {\n isConnected: this.isConnected(),\n isVerified: this.isVerified,\n hasKeys: !!(this.encryptionKey && this.macKey && this.metadataKey),\n hasLastCalculation: !!this.lastSecurityCalculation\n });\n \n // Send an event about security level update\n document.dispatchEvent(new CustomEvent('security-level-updated', {\n detail: { \n timestamp: Date.now(), \n manager: 'webrtc',\n webrtcManager: this,\n isConnected: this.isConnected(),\n isVerified: this.isVerified,\n hasKeys: !!(this.encryptionKey && this.macKey && this.metadataKey),\n lastCalculation: this.lastSecurityCalculation\n }\n }));\n \n // FIX: Force header refresh with correct manager\n setTimeout(() => {\n // Removed global callback - use event system instead\n // if (window.forceHeaderSecurityUpdate) {\n // window.forceHeaderSecurityUpdate(this);\n // }\n }, 100);\n \n // FIX: Direct update if there is a calculation\n if (this.lastSecurityCalculation) {\n document.dispatchEvent(new CustomEvent('real-security-calculated', {\n detail: {\n securityData: this.lastSecurityCalculation,\n webrtcManager: this,\n timestamp: Date.now()\n }\n }));\n }\n \n } catch (error) {\n this._secureLog('error', '\u274C Error in notifySecurityUpdate', {\n error: error.message\n });\n }\n }\n\n handleSystemMessage(message) {\n this._secureLog('debug', '\uD83D\uDD27 Handling system message:', { type: message.type });\n \n switch (message.type) {\n case 'heartbeat':\n this.handleHeartbeat();\n break;\n case 'verification':\n this.handleVerificationRequest(message.data);\n break;\n case 'verification_response':\n this.handleVerificationResponse(message.data);\n break;\n case 'sas_code':\n this.handleSASCode(message.data);\n break;\n case 'verification_confirmed':\n this.handleVerificationConfirmed(message.data);\n break;\n case 'verification_both_confirmed':\n this.handleVerificationBothConfirmed(message.data);\n break;\n case 'peer_disconnect':\n this.handlePeerDisconnectNotification(message);\n break;\n case 'key_rotation_signal':\n this._secureLog('debug', '\uD83D\uDD04 Key rotation signal received (ignored for stability)');\n break;\n case 'key_rotation_ready':\n this._secureLog('debug', '\uD83D\uDD04 Key rotation ready signal received (ignored for stability)');\n break;\n case 'security_upgrade':\n this._secureLog('debug', '\uD83D\uDD12 Security upgrade notification received:', { type: message.type });\n // Security upgrade messages are handled internally, not displayed to user\n // to prevent duplicate system messages\n break;\n default:\n this._secureLog('debug', '\uD83D\uDD27 Unknown system message type:', { type: message.type });\n }\n }\n\n // ============================================\n // FUNCTION MANAGEMENT METHODS\n // ============================================\n\n // Method to enable Stage 2 functions\n enableStage2Security() {\n if (this.sessionConstraints?.hasPacketReordering) {\n this.securityFeatures.hasPacketReordering = true;\n this.reorderingConfig.enabled = true;\n }\n \n if (this.sessionConstraints?.hasAntiFingerprinting) {\n this.securityFeatures.hasAntiFingerprinting = true;\n this.antiFingerprintingConfig.enabled = true;\n if (this.currentSecurityLevel === 'enhanced') {\n this.antiFingerprintingConfig.randomizeSizes = false;\n this.antiFingerprintingConfig.maskPatterns = false;\n this.antiFingerprintingConfig.useRandomHeaders = false;\n }\n }\n \n this.notifySecurityUpgrade(2);\n setTimeout(() => {\n this.calculateAndReportSecurityLevel();\n }, 500);\n }\n\n // Method to enable Stage 3 features (traffic obfuscation)\n enableStage3Security() {\n if (this.currentSecurityLevel !== 'maximum') {\n this._secureLog('info', '\uD83D\uDD12 Stage 3 features only available for premium sessions');\n return;\n }\n \n if (this.sessionConstraints?.hasMessageChunking) {\n this.securityFeatures.hasMessageChunking = true;\n this.chunkingConfig.enabled = true;\n }\n \n if (this.sessionConstraints?.hasFakeTraffic) {\n this.securityFeatures.hasFakeTraffic = true;\n this.fakeTrafficConfig.enabled = true;\n this.startFakeTrafficGeneration();\n }\n \n this.notifySecurityUpgrade(3);\n setTimeout(() => {\n this.calculateAndReportSecurityLevel();\n }, 500);\n }\n\n // Method for enabling Stage 4 functions (maximum safety)\n enableStage4Security() {\n if (this.currentSecurityLevel !== 'maximum') {\n this._secureLog('info', '\uD83D\uDD12 Stage 4 features only available for premium sessions');\n return;\n }\n \n if (this.sessionConstraints?.hasDecoyChannels && this.isConnected() && this.isVerified) {\n this.securityFeatures.hasDecoyChannels = true;\n this.decoyChannelConfig.enabled = true;\n \n try {\n this.initializeDecoyChannels();\n } catch (error) {\n this._secureLog('warn', '\u26A0\uFE0F Decoy channels initialization failed:', { details: error.message });\n this.securityFeatures.hasDecoyChannels = false;\n this.decoyChannelConfig.enabled = false;\n }\n }\n \n // Full anti-fingerprinting for maximum sessions\n if (this.sessionConstraints?.hasAntiFingerprinting) {\n this.antiFingerprintingConfig.randomizeSizes = true;\n this.antiFingerprintingConfig.maskPatterns = true;\n this.antiFingerprintingConfig.useRandomHeaders = false; \n }\n \n this.notifySecurityUpgrade(4);\n setTimeout(() => {\n this.calculateAndReportSecurityLevel();\n }, 500);\n }\n\n forceSecurityUpdate() {\n setTimeout(() => {\n this.calculateAndReportSecurityLevel();\n this.notifySecurityUpdate();\n }, 100);\n }\n\n // Method for getting security status\n getSecurityStatus() {\n const activeFeatures = Object.entries(this.securityFeatures)\n .filter(([key, value]) => value === true)\n .map(([key]) => key);\n \n const stage = this.currentSecurityLevel === 'basic' ? 1 : \n this.currentSecurityLevel === 'enhanced' ? 2 :\n this.currentSecurityLevel === 'maximum' ? 4 : 1;\n \n return {\n stage: stage,\n sessionType: this.currentSessionType,\n securityLevel: this.currentSecurityLevel,\n activeFeatures: activeFeatures,\n totalFeatures: Object.keys(this.securityFeatures).length,\n activeFeaturesCount: activeFeatures.length,\n activeFeaturesNames: activeFeatures,\n sessionConstraints: this.sessionConstraints\n };\n }\n\n // Method to notify UI about security update\n notifySecurityUpgrade(stage) {\n const stageNames = {\n 1: 'Basic Enhanced',\n 2: 'Medium Security', \n 3: 'High Security',\n 4: 'Maximum Security'\n };\n \n const message = `\uD83D\uDD12 Security upgraded to Stage ${stage}: ${stageNames[stage]}`;\n \n // Avoid duplicate security-upgrade notifications\n if (!this.securityUpgradeNotificationSent || this.lastSecurityUpgradeStage !== stage) {\n this.securityUpgradeNotificationSent = true;\n this.lastSecurityUpgradeStage = stage;\n \n // Notify local UI via onMessage\n if (this.onMessage) {\n this.deliverMessageToUI(message, 'system');\n }\n }\n\n // Send security upgrade notification to peer via WebRTC\n if (this.dataChannel && this.dataChannel.readyState === 'open') {\n try {\n const securityNotification = {\n type: 'security_upgrade',\n stage: stage,\n stageName: stageNames[stage],\n message: message,\n timestamp: Date.now()\n };\n \n this._secureLog('debug', '\uD83D\uDD12 Sending security upgrade notification to peer:', { type: securityNotification.type, stage: securityNotification.stage });\n this.dataChannel.send(JSON.stringify(securityNotification));\n } catch (error) {\n this._secureLog('warn', '\u26A0\uFE0F Failed to send security upgrade notification to peer:', { details: error.message });\n }\n }\n\n const status = this.getSecurityStatus();\n }\n\n async calculateAndReportSecurityLevel() {\n try {\n if (!window.EnhancedSecureCryptoUtils) {\n this._secureLog('warn', '\u26A0\uFE0F EnhancedSecureCryptoUtils not available for security calculation');\n return null;\n }\n\n if (!this.isConnected() || !this.isVerified || !this.encryptionKey || !this.macKey) {\n this._secureLog('debug', '\u26A0\uFE0F WebRTC not ready for security calculation', {\n connected: this.isConnected(),\n verified: this.isVerified,\n hasEncryptionKey: !!this.encryptionKey,\n hasMacKey: !!this.macKey\n });\n return null;\n }\n\n this._secureLog('debug', '\uD83D\uDD0D Calculating real security level', {\n managerState: 'ready',\n hasAllKeys: !!(this.encryptionKey && this.macKey && this.metadataKey)\n });\n \n const securityData = await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(this);\n \n this._secureLog('info', '\uD83D\uDD10 Real security level calculated', {\n hasSecurityLevel: !!securityData.level,\n scoreRange: securityData.score > 80 ? 'high' : securityData.score > 50 ? 'medium' : 'low',\n checksRatio: `${securityData.passedChecks}/${securityData.totalChecks}`,\n isRealCalculation: securityData.isRealData\n });\n\n this.lastSecurityCalculation = securityData;\n\n document.dispatchEvent(new CustomEvent('real-security-calculated', {\n detail: {\n securityData: securityData,\n webrtcManager: this,\n timestamp: Date.now(),\n source: 'calculateAndReportSecurityLevel'\n }\n }));\n\n if (securityData.isRealData && this.onMessage) {\n if (!this.securityCalculationNotificationSent || this.lastSecurityCalculationLevel !== securityData.level) {\n this.securityCalculationNotificationSent = true;\n this.lastSecurityCalculationLevel = securityData.level;\n \n const message = `\uD83D\uDD12 Security Level: ${securityData.level} (${securityData.score}%) - ${securityData.passedChecks}/${securityData.totalChecks} checks passed`;\n this.deliverMessageToUI(message, 'system');\n }\n }\n \n return securityData;\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to calculate real security level', {\n errorType: error.constructor.name\n });\n return null;\n }\n }\n\n // ============================================\n // AUTOMATIC STEP-BY-STEP SWITCHING ON\n // ============================================\n\n // Method for automatic feature enablement with stability check\n async autoEnableSecurityFeatures() {\n if (this.currentSessionType === 'demo') {\n this._secureLog('info', '\uD83D\uDD12 Demo session - keeping basic security only');\n await this.calculateAndReportSecurityLevel();\n this.notifySecurityUpgrade(1);\n return;\n }\n\n const checkStability = () => {\n const isStable = this.isConnected() && \n this.isVerified && \n this.connectionAttempts === 0 && \n this.messageQueue.length === 0 &&\n this.peerConnection?.connectionState === 'connected';\n return isStable;\n };\n \n this._secureLog('info', `\uD83D\uDD12 ${this.currentSessionType} session - starting graduated security activation`);\n await this.calculateAndReportSecurityLevel();\n this.notifySecurityUpgrade(1);\n \n if (this.currentSecurityLevel === 'enhanced' || this.currentSecurityLevel === 'maximum') {\n setTimeout(async () => {\n if (checkStability()) {\n console.log('\u2705 Activating Stage 2 for paid session');\n this.enableStage2Security();\n await this.calculateAndReportSecurityLevel(); \n \n // For maximum sessions, turn on Stage 3 and 4\n if (this.currentSecurityLevel === 'maximum') {\n setTimeout(async () => {\n if (checkStability()) {\n console.log('\u2705 Activating Stage 3 for premium session');\n this.enableStage3Security();\n await this.calculateAndReportSecurityLevel();\n \n setTimeout(async () => {\n if (checkStability()) {\n console.log('\u2705 Activating Stage 4 for premium session');\n this.enableStage4Security();\n await this.calculateAndReportSecurityLevel();\n }\n }, 20000);\n }\n }, 15000);\n }\n }\n }, 10000);\n }\n }\n\n // ============================================\n // CONNECTION MANAGEMENT WITH ENHANCED SECURITY\n // ============================================\n\n async establishConnection() {\n try {\n // Initialize enhanced security features\n await this.initializeEnhancedSecurity();\n \n // Start fake traffic generation\n if (this.fakeTrafficConfig.enabled) {\n this.startFakeTrafficGeneration();\n }\n \n // Initialize decoy channels\n if (this.decoyChannelConfig.enabled) {\n this.initializeDecoyChannels();\n }\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to establish enhanced connection:', { errorType: error?.constructor?.name || 'Unknown' });\n // Do not close the connection on setup errors \u2014 just log and continue\n this.onStatusChange('disconnected');\n throw error;\n }\n }\n\n disconnect() {\n try {\n console.log('\uD83D\uDD0C Disconnecting WebRTC Manager...');\n \n // Cleanup file transfer system\n if (this.fileTransferSystem) {\n console.log('\uD83E\uDDF9 Cleaning up file transfer system during disconnect...');\n this.fileTransferSystem.cleanup();\n this.fileTransferSystem = null;\n }\n \n // Stop fake traffic generation\n this.stopFakeTrafficGeneration();\n \n // Stop decoy traffic\n for (const [channelName, timer] of this.decoyTimers.entries()) {\n clearTimeout(timer);\n }\n this.decoyTimers.clear();\n \n // Close decoy channels\n for (const [channelName, channel] of this.decoyChannels.entries()) {\n if (channel.readyState === 'open') {\n channel.close();\n }\n }\n this.decoyChannels.clear();\n \n // Clean up packet buffer\n this.packetBuffer.clear();\n \n // Clean up chunk queue\n this.chunkQueue = [];\n \n // Wipe ephemeral keys for PFS on disconnect\n this._wipeEphemeralKeys();\n \n // Hard wipe old keys for PFS\n this._hardWipeOldKeys();\n\n // Clear verification states\n this._clearVerificationStates();\n\n } catch (error) {\n this._secureLog('error', '\u274C Error during enhanced disconnect:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n }\n\n /**\n * Clear all verification states and data\n * Called when verification is rejected or connection is terminated\n */\n _clearVerificationStates() {\n try {\n console.log('\uD83E\uDDF9 Clearing verification states...');\n \n // Clear verification states\n this.localVerificationConfirmed = false;\n this.remoteVerificationConfirmed = false;\n this.bothVerificationsConfirmed = false;\n this.isVerified = false;\n this.verificationCode = null;\n this.pendingSASCode = null;\n \n // Clear key fingerprint and connection data\n this.keyFingerprint = null;\n this.expectedDTLSFingerprint = null;\n this.connectionId = null;\n \n // Clear processed message IDs\n this.processedMessageIds.clear();\n \n // Reset notification flags\n this.verificationNotificationSent = false;\n this.verificationInitiationSent = false;\n \n console.log('\u2705 Verification states cleared successfully');\n \n } catch (error) {\n this._secureLog('error', '\u274C Error clearing verification states:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n }\n\n // Start periodic cleanup for rate limiting and security\n startPeriodicCleanup() {\n // Cleanup moved to unified scheduler\n this._secureLog('info', '\uD83D\uDD27 Periodic cleanup moved to unified scheduler');\n }\n\n // Calculate current security level with real verification\n async calculateSecurityLevel() {\n return await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(this);\n }\n\n // PFS: Check if key rotation is needed\n shouldRotateKeys() {\n if (!this.isConnected() || !this.isVerified) {\n return false;\n }\n \n const now = Date.now();\n const timeSinceLastRotation = now - this.lastKeyRotation;\n \n // Rotate keys every 5 minutes or after 100 messages\n return timeSinceLastRotation > this.keyRotationInterval || \n this.messageCounter % 100 === 0;\n }\n\n // PFS: Rotate encryption keys for Perfect Forward Secrecy\n async rotateKeys() {\n return this._withMutex('keyOperation', async (operationId) => {\n this._secureLog('info', '\uD83D\uDD04 Starting key rotation with mutex', {\n operationId: operationId\n });\n \n // Validate state inside the critical section\n if (!this.isConnected() || !this.isVerified) {\n this._secureLog('warn', '\u26A0\uFE0F Key rotation aborted - connection not ready', {\n operationId: operationId,\n isConnected: this.isConnected(),\n isVerified: this.isVerified\n });\n return false;\n }\n \n // Ensure rotation is not already in progress\n if (this._keySystemState.isRotating) {\n this._secureLog('warn', '\u26A0\uFE0F Key rotation already in progress', {\n operationId: operationId\n });\n return false;\n }\n \n try {\n // Set rotation flag\n this._keySystemState.isRotating = true;\n this._keySystemState.lastOperation = 'rotation';\n this._keySystemState.lastOperationTime = Date.now();\n \n // Send rotation signal to peer\n const rotationSignal = {\n type: 'key_rotation_signal',\n newVersion: this.currentKeyVersion + 1,\n timestamp: Date.now(),\n operationId: operationId\n };\n \n if (this.dataChannel && this.dataChannel.readyState === 'open') {\n this.dataChannel.send(JSON.stringify(rotationSignal));\n } else {\n throw new Error('Data channel not ready for key rotation');\n }\n \n // Perform hard wipe of old keys for real PFS\n this._hardWipeOldKeys();\n \n // Wait for peer confirmation\n return new Promise((resolve) => {\n this.pendingRotation = {\n newVersion: this.currentKeyVersion + 1,\n operationId: operationId,\n resolve: resolve,\n timeout: setTimeout(() => {\n this._secureLog('error', '\u26A0\uFE0F Key rotation timeout', {\n operationId: operationId\n });\n this._keySystemState.isRotating = false;\n this.pendingRotation = null;\n resolve(false);\n }, 10000) // 10 seconds timeout\n };\n });\n \n } catch (error) {\n this._secureLog('error', '\u274C Key rotation failed in critical section', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n this._keySystemState.isRotating = false;\n return false;\n }\n }, 10000); // 10 seconds timeout for the entire operation\n }\n\n // Real PFS - Clean up old keys with hard wipe\n cleanupOldKeys() {\n const now = Date.now();\n const maxKeyAge = EnhancedSecureWebRTCManager.LIMITS.MAX_KEY_AGE; // 15 minutes - keys older than this are deleted\n \n let wipedKeysCount = 0;\n \n for (const [version, keySet] of this.oldKeys.entries()) {\n if (now - keySet.timestamp > maxKeyAge) {\n // Hard wipe old keys before deletion\n if (keySet.encryptionKey) {\n this._secureWipeMemory(keySet.encryptionKey, 'pfs_cleanup_wipe');\n }\n if (keySet.macKey) {\n this._secureWipeMemory(keySet.macKey, 'pfs_cleanup_wipe');\n }\n if (keySet.metadataKey) {\n this._secureWipeMemory(keySet.metadataKey, 'pfs_cleanup_wipe');\n }\n \n // Clear references\n keySet.encryptionKey = null;\n keySet.macKey = null;\n keySet.metadataKey = null;\n keySet.keyFingerprint = null;\n \n this.oldKeys.delete(version);\n wipedKeysCount++;\n \n this._secureLog('info', '\uD83E\uDDF9 Old PFS keys hard wiped and cleaned up', {\n version: version,\n age: Math.round((now - keySet.timestamp) / 1000) + 's',\n timestamp: Date.now()\n });\n }\n }\n \n if (wipedKeysCount > 0) {\n this._secureLog('info', `\u2705 PFS cleanup completed: ${wipedKeysCount} keys hard wiped`, {\n timestamp: Date.now()\n });\n }\n }\n\n // PFS: Get keys for specific version (for decryption)\n getKeysForVersion(version) {\n // First, we check the old keys (including version 0).\n const oldKeySet = this.oldKeys.get(version);\n if (oldKeySet && oldKeySet.encryptionKey && oldKeySet.macKey && oldKeySet.metadataKey) {\n return {\n encryptionKey: oldKeySet.encryptionKey,\n macKey: oldKeySet.macKey,\n metadataKey: oldKeySet.metadataKey\n };\n }\n \n // If this is the current version, return the current keys.\n if (version === this.currentKeyVersion) {\n if (this.encryptionKey && this.macKey && this.metadataKey) {\n return {\n encryptionKey: this.encryptionKey,\n macKey: this.macKey,\n metadataKey: this.metadataKey\n };\n }\n }\n \n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'No valid keys found for version', {\n requestedVersion: version,\n currentVersion: this.currentKeyVersion,\n availableVersions: Array.from(this.oldKeys.keys())\n });\n \n return null;\n }\n\n createPeerConnection() {\n const config = {\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun1.l.google.com:19302' },\n { urls: 'stun:stun2.l.google.com:19302' },\n { urls: 'stun:stun3.l.google.com:19302' },\n { urls: 'stun:stun4.l.google.com:19302' }\n ],\n iceCandidatePoolSize: 10,\n bundlePolicy: 'balanced'\n };\n\n this.peerConnection = new RTCPeerConnection(config);\n\n this.peerConnection.onconnectionstatechange = () => {\n const state = this.peerConnection.connectionState;\n console.log('Connection state:', state);\n \n if (state === 'connected' && !this.isVerified) {\n this.onStatusChange('verifying');\n } else if (state === 'connected' && this.isVerified) {\n this.onStatusChange('connected');\n } else if (state === 'disconnected' || state === 'closed') {\n // If this is an intentional disconnect, clear immediately.\n if (this.intentionalDisconnect) {\n this.onStatusChange('disconnected');\n setTimeout(() => this.disconnect(), 100);\n } else {\n this.onStatusChange('disconnected');\n // Clear verification states on unexpected disconnect\n this._clearVerificationStates();\n }\n } else if (state === 'failed') {\n // Do not auto-reconnect to avoid closing the session on errors\n this.onStatusChange('disconnected');\n // if (!this.intentionalDisconnect && this.connectionAttempts < this.maxConnectionAttempts) {\n // this.connectionAttempts++;\n // setTimeout(() => this.retryConnection(), 2000);\n // } else {\n // this.onStatusChange('disconnected');\n // // Do not call cleanupConnection automatically for 'failed'\n // // to avoid closing the session on connection errors\n // }\n } else {\n this.onStatusChange(state);\n }\n };\n\n this.peerConnection.ondatachannel = (event) => {\n console.log('\uD83D\uDD17 Data channel received:', {\n channelLabel: event.channel.label,\n channelState: event.channel.readyState,\n isInitiator: this.isInitiator,\n channelId: event.channel.id,\n protocol: event.channel.protocol\n });\n \n // CRITICAL: Store the received data channel\n if (event.channel.label === 'securechat') {\n console.log('\uD83D\uDD17 MAIN DATA CHANNEL RECEIVED (answerer side)');\n this.dataChannel = event.channel;\n this.setupDataChannel(event.channel);\n } else {\n console.log('\uD83D\uDD17 ADDITIONAL DATA CHANNEL RECEIVED:', event.channel.label);\n // Handle additional channels (heartbeat, etc.)\n if (event.channel.label === 'heartbeat') {\n this.heartbeatChannel = event.channel;\n }\n }\n };\n }\n\n setupDataChannel(channel) {\n console.log('\uD83D\uDD17 setupDataChannel called:', {\n channelLabel: channel.label,\n channelState: channel.readyState,\n isInitiator: this.isInitiator,\n isVerified: this.isVerified\n });\n\n this.dataChannel = channel;\n\n this.dataChannel.onopen = async () => {\n console.log('\uD83D\uDD17 Data channel opened:', {\n isInitiator: this.isInitiator,\n isVerified: this.isVerified,\n dataChannelState: this.dataChannel.readyState,\n dataChannelLabel: this.dataChannel.label\n });\n // Configure backpressure for large transfers\n try {\n if (this.dataChannel && typeof this.dataChannel.bufferedAmountLowThreshold === 'number') {\n // 1 MB threshold for bufferedamountlow event\n this.dataChannel.bufferedAmountLowThreshold = 1024 * 1024;\n }\n } catch (e) {\n // ignore\n }\n \n try {\n await this.establishConnection();\n\n this.initializeFileTransfer();\n \n } catch (error) {\n this._secureLog('error', '\u274C Error in establishConnection:', { errorType: error?.constructor?.name || 'Unknown' });\n // Continue despite errors\n }\n \n // CRITICAL: Send pending SAS code if available\n if (this.pendingSASCode && this.dataChannel && this.dataChannel.readyState === 'open') {\n try {\n const sasPayload = {\n type: 'sas_code',\n data: {\n code: this.pendingSASCode,\n timestamp: Date.now(),\n verificationMethod: 'SAS',\n securityLevel: 'MITM_PROTECTION_REQUIRED'\n }\n };\n console.log('\uD83D\uDCE4 Sending pending SAS code to Answer side:', this.pendingSASCode);\n this.dataChannel.send(JSON.stringify(sasPayload));\n this.pendingSASCode = null; // Clear after sending\n } catch (error) {\n console.error('Failed to send pending SAS code to Answer side:', error);\n }\n } else if (this.pendingSASCode) {\n console.log('\u26A0\uFE0F Cannot send SAS code - dataChannel not ready:', {\n hasDataChannel: !!this.dataChannel,\n readyState: this.dataChannel?.readyState,\n pendingSASCode: this.pendingSASCode\n });\n }\n \n if (this.isVerified) {\n this.onStatusChange('connected');\n this.processMessageQueue();\n \n setTimeout(async () => {\n await this.calculateAndReportSecurityLevel();\n this.autoEnableSecurityFeatures();\n this.notifySecurityUpdate();\n }, 500);\n } else {\n this.onStatusChange('verifying');\n this.initiateVerification();\n }\n this.startHeartbeat();\n };\n\n this.dataChannel.onclose = () => {\n if (!this.intentionalDisconnect) {\n this.onStatusChange('disconnected');\n // Clear verification states on data channel close\n this._clearVerificationStates();\n \n if (!this.connectionClosedNotificationSent) {\n this.connectionClosedNotificationSent = true;\n this.deliverMessageToUI('\uD83D\uDD0C Enhanced secure connection closed. Check connection status.', 'system');\n }\n } else {\n this.onStatusChange('disconnected');\n // Clear verification states on intentional disconnect\n this._clearVerificationStates();\n \n if (!this.connectionClosedNotificationSent) {\n this.connectionClosedNotificationSent = true;\n this.deliverMessageToUI('\uD83D\uDD0C Enhanced secure connection closed', 'system');\n }\n }\n \n // Wipe ephemeral keys when session ends for PFS\n this._wipeEphemeralKeys();\n \n this.stopHeartbeat();\n this.isVerified = false;\n };\n\n // FIX 2: Remove mutex entirely from message processing path\n this.dataChannel.onmessage = async (event) => {\n try {\n console.log('\uD83D\uDCE8 Raw message received:', {\n dataType: typeof event.data,\n dataLength: event.data?.length || event.data?.byteLength || 0,\n isString: typeof event.data === 'string'\n });\n\n // IMPORTANT: Process ALL messages WITHOUT mutex\n if (typeof event.data === 'string') {\n try {\n const parsed = JSON.parse(event.data);\n console.log('\uD83D\uDCE8 Parsed message:', {\n type: parsed.type,\n hasData: !!parsed.data,\n timestamp: parsed.timestamp\n });\n \n // ============================================\n // CRITICAL: FILE MESSAGES (WITHOUT MUTEX)\n // ============================================\n \n const fileMessageTypes = [\n 'file_transfer_start',\n 'file_transfer_response', \n 'file_chunk',\n 'chunk_confirmation',\n 'file_transfer_complete',\n 'file_transfer_error'\n ];\n \n if (parsed.type && fileMessageTypes.includes(parsed.type)) {\n console.log('\uD83D\uDCC1 File message intercepted at WebRTC level:', parsed.type);\n\n if (!this.fileTransferSystem) {\n try {\n if (this.isVerified && this.dataChannel && this.dataChannel.readyState === 'open') {\n this.initializeFileTransfer();\n\n let attempts = 0;\n const maxAttempts = 30;\n while (!this.fileTransferSystem && attempts < maxAttempts) {\n await new Promise(resolve => setTimeout(resolve, 100));\n attempts++;\n }\n }\n } catch (initError) {\n this._secureLog('error', '\u274C Failed to initialize file transfer system for receiver:', { errorType: initError?.constructor?.name || 'Unknown' });\n }\n }\n\n if (this.fileTransferSystem) {\n console.log('\uD83D\uDCC1 Forwarding to local file transfer system:', parsed.type);\n await this.fileTransferSystem.handleFileMessage(parsed);\n return;\n }\n // Attempt lazy initialization on receiver side\n this._secureLog('warn', '\u26A0\uFE0F File transfer system not ready, attempting lazy init...');\n try {\n await this._ensureFileTransferReady();\n if (this.fileTransferSystem) {\n await this.fileTransferSystem.handleFileMessage(parsed);\n return;\n }\n } catch (e) {\n this._secureLog('error', '\u274C Lazy init of file transfer failed:', { errorType: e?.message || e?.constructor?.name || 'Unknown' });\n }\n this._secureLog('error', '\u274C No file transfer system available for:', { errorType: parsed.type?.constructor?.name || 'Unknown' });\n return; // IMPORTANT: Do not process further\n }\n \n // ============================================\n // SYSTEM MESSAGES (WITHOUT MUTEX)\n // ============================================\n \n if (parsed.type && ['heartbeat', 'verification', 'verification_response', 'verification_confirmed', 'verification_both_confirmed', 'sas_code', 'peer_disconnect', 'security_upgrade'].includes(parsed.type)) {\n console.log('\uD83D\uDD27 System message detected:', parsed.type);\n this.handleSystemMessage(parsed);\n return;\n }\n \n // ============================================\n // REGULAR USER MESSAGES (WITHOUT MUTEX)\n // ============================================\n \n if (parsed.type === 'message' && parsed.data) {\n console.log('\uD83D\uDCDD User message detected:', parsed.data.substring(0, 50));\n if (this.onMessage) {\n this.deliverMessageToUI(parsed.data, 'received');\n }\n return;\n }\n \n // ============================================\n // ENHANCED MESSAGES (WITHOUT MUTEX)\n // ============================================\n \n if (parsed.type === 'enhanced_message' && parsed.data) {\n console.log('\uD83D\uDD10 Enhanced message detected, processing...');\n await this._processEnhancedMessageWithoutMutex(parsed);\n return;\n }\n \n // ============================================\n // FAKE MESSAGES (WITHOUT MUTEX)\n // ============================================\n \n if (parsed.type === 'fake') {\n console.log('\uD83C\uDFAD Fake message blocked:', parsed.pattern);\n return;\n }\n \n // ============================================\n // UNKNOWN MESSAGE TYPES\n // ============================================\n \n console.log('\u2753 Unknown message type:', parsed.type);\n \n } catch (jsonError) {\n // Not JSON \u2014 treat as regular text message\n console.log('\uD83D\uDCC4 Non-JSON message detected, treating as text');\n if (this.onMessage) {\n this.deliverMessageToUI(event.data, 'received');\n }\n return;\n }\n } else if (event.data instanceof ArrayBuffer) {\n // Binary data \u2014 process WITHOUT mutex\n console.log('\uD83D\uDD22 Binary data received, processing...');\n await this._processBinaryDataWithoutMutex(event.data);\n } else {\n console.log('\u2753 Unknown data type:', typeof event.data);\n }\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to process message in onmessage:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n };\n }\n // FIX 4: New method for processing binary data WITHOUT mutex\n async _processBinaryDataWithoutMutex(data) {\n try {\n console.log('\uD83D\uDD22 Processing binary data without mutex...');\n \n // Apply security layers WITHOUT mutex\n let processedData = data;\n \n // Nested Encryption Removal (if enabled)\n if (this.securityFeatures.hasNestedEncryption && \n this.nestedEncryptionKey && \n processedData instanceof ArrayBuffer &&\n processedData.byteLength > 12) {\n \n try {\n processedData = await this.removeNestedEncryption(processedData);\n } catch (error) {\n this._secureLog('warn', '\u26A0\uFE0F Nested decryption failed, continuing with original data');\n }\n }\n \n // Packet Padding Removal (if enabled)\n if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) {\n try {\n processedData = this.removePacketPadding(processedData);\n } catch (error) {\n this._secureLog('warn', '\u26A0\uFE0F Packet padding removal failed, continuing with original data');\n }\n }\n \n // Anti-Fingerprinting Removal (if enabled)\n if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) {\n try {\n processedData = this.removeAntiFingerprinting(processedData);\n } catch (error) {\n this._secureLog('warn', '\u26A0\uFE0F Anti-fingerprinting removal failed, continuing with original data');\n }\n }\n \n // Convert to text\n if (processedData instanceof ArrayBuffer) {\n const textData = new TextDecoder().decode(processedData);\n \n // Check for fake messages\n try {\n const content = JSON.parse(textData);\n if (content.type === 'fake' || content.isFakeTraffic === true) {\n console.log(`\uD83C\uDFAD BLOCKED: Binary fake message: ${content.pattern || 'unknown'}`);\n return;\n }\n } catch (e) {\n // Not JSON \u2014 fine for plain text\n }\n \n // Deliver message to user\n if (this.onMessage) {\n this.deliverMessageToUI(textData, 'received');\n }\n }\n \n } catch (error) {\n this._secureLog('error', '\u274C Error processing binary data:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n }\n // FIX 3: New method for processing enhanced messages WITHOUT mutex\n async _processEnhancedMessageWithoutMutex(parsedMessage) {\n try {\n console.log('\uD83D\uDD10 Processing enhanced message without mutex...');\n \n if (!this.encryptionKey || !this.macKey || !this.metadataKey) {\n this._secureLog('error', '\u274C Missing encryption keys for enhanced message');\n return;\n }\n \n const decryptedResult = await window.EnhancedSecureCryptoUtils.decryptMessage(\n parsedMessage.data,\n this.encryptionKey,\n this.macKey,\n this.metadataKey\n );\n \n if (decryptedResult && decryptedResult.message) {\n console.log('\u2705 Enhanced message decrypted successfully');\n \n // Try parsing JSON and showing nested text if it's a chat message\n try {\n const decryptedContent = JSON.parse(decryptedResult.message);\n if (decryptedContent.type === 'fake' || decryptedContent.isFakeTraffic === true) {\n console.log(`\uFFFD\uFFFD BLOCKED: Encrypted fake message: ${decryptedContent.pattern || 'unknown'}`);\n return;\n }\n if (decryptedContent && decryptedContent.type === 'message' && typeof decryptedContent.data === 'string') {\n if (this.onMessage) {\n this.deliverMessageToUI(decryptedContent.data, 'received');\n }\n return;\n }\n } catch (e) {\n // Not JSON \u2014 fine for plain text\n }\n \n // Otherwise pass as-is\n if (this.onMessage) {\n this.deliverMessageToUI(decryptedResult.message, 'received');\n }\n } else {\n this._secureLog('warn', '\u26A0\uFE0F No message content in decrypted result');\n }\n \n } catch (error) {\n this._secureLog('error', '\u274C Error processing enhanced message:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n }\n /**\n * Creates a unique ID for an operation\n */\n _generateOperationId() {\n return `op_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n /**\n * Atomic mutex acquisition with enhanced race condition protection\n */\n async _acquireMutex(mutexName, operationId, timeout = 5000) {\n // Build correct mutex property name\n const mutexPropertyName = `_${mutexName}Mutex`;\n const mutex = this[mutexPropertyName];\n \n if (!mutex) {\n this._secureLog('error', `\u274C Unknown mutex: ${mutexName}`, {\n mutexPropertyName: mutexPropertyName,\n availableMutexes: this._getAvailableMutexes(),\n operationId: operationId\n });\n throw new Error(`Unknown mutex: ${mutexName}. Available: ${this._getAvailableMutexes().join(', ')}`);\n }\n \n // Validate operation ID\n if (!operationId || typeof operationId !== 'string') {\n throw new Error('Invalid operation ID for mutex acquisition');\n }\n \n return new Promise((resolve, reject) => {\n // Atomic lock attempt with immediate state check\n const attemptLock = () => {\n // Check if mutex is already locked by this operation\n if (mutex.lockId === operationId) {\n this._secureLog('warn', `\u26A0\uFE0F Mutex '${mutexName}' already locked by same operation`, {\n operationId: operationId\n });\n resolve();\n return;\n }\n \n // Atomic check and lock operation\n if (!mutex.locked) {\n // Set lock state atomically\n mutex.locked = true;\n mutex.lockId = operationId;\n mutex.lockTime = Date.now();\n \n this._secureLog('debug', `\uD83D\uDD12 Mutex '${mutexName}' acquired atomically`, {\n operationId: operationId,\n lockTime: mutex.lockTime\n });\n \n // Set timeout for automatic release with enhanced validation\n mutex.lockTimeout = setTimeout(() => {\n // Enhanced timeout handling with state validation\n this._handleMutexTimeout(mutexName, operationId, timeout);\n }, timeout);\n \n resolve();\n } else {\n // Add to queue with timeout\n const queueItem = { \n resolve, \n reject, \n operationId,\n timestamp: Date.now(),\n timeout: setTimeout(() => {\n // Remove from queue on timeout\n const index = mutex.queue.findIndex(item => item.operationId === operationId);\n if (index !== -1) {\n mutex.queue.splice(index, 1);\n reject(new Error(`Mutex acquisition timeout for '${mutexName}'`));\n }\n }, timeout)\n };\n \n mutex.queue.push(queueItem);\n \n this._secureLog('debug', `\u23F3 Operation queued for mutex '${mutexName}'`, {\n operationId: operationId,\n queueLength: mutex.queue.length,\n currentLockId: mutex.lockId\n });\n }\n };\n \n // Execute lock attempt immediately\n attemptLock();\n });\n }\n\n /**\n * Enhanced mutex release with strict validation and error handling\n */\n _releaseMutex(mutexName, operationId) {\n // Validate input parameters\n if (!mutexName || typeof mutexName !== 'string') {\n throw new Error('Invalid mutex name provided for release');\n }\n \n if (!operationId || typeof operationId !== 'string') {\n throw new Error('Invalid operation ID provided for mutex release');\n }\n \n // Build correct mutex property name\n const mutexPropertyName = `_${mutexName}Mutex`;\n const mutex = this[mutexPropertyName];\n \n if (!mutex) {\n this._secureLog('error', `\u274C Unknown mutex for release: ${mutexName}`, {\n mutexPropertyName: mutexPropertyName,\n availableMutexes: this._getAvailableMutexes(),\n operationId: operationId\n });\n throw new Error(`Unknown mutex for release: ${mutexName}`);\n }\n \n // Strict validation of lock ownership\n if (mutex.lockId !== operationId) {\n this._secureLog('error', `\u274C CRITICAL: Invalid mutex release attempt - potential race condition`, {\n mutexName: mutexName,\n expectedLockId: mutex.lockId,\n providedOperationId: operationId,\n mutexState: {\n locked: mutex.locked,\n lockTime: mutex.lockTime,\n queueLength: mutex.queue.length\n }\n });\n \n // Throw error instead of silent failure\n throw new Error(`Invalid mutex release attempt for '${mutexName}': expected '${mutex.lockId}', got '${operationId}'`);\n }\n \n // Validate mutex is actually locked\n if (!mutex.locked) {\n this._secureLog('error', `\u274C CRITICAL: Attempting to release unlocked mutex`, {\n mutexName: mutexName,\n operationId: operationId,\n mutexState: {\n locked: mutex.locked,\n lockId: mutex.lockId,\n lockTime: mutex.lockTime\n }\n });\n throw new Error(`Attempting to release unlocked mutex: ${mutexName}`);\n }\n \n try {\n // Clear timeout first\n if (mutex.lockTimeout) {\n clearTimeout(mutex.lockTimeout);\n mutex.lockTimeout = null;\n }\n \n // Calculate lock duration for monitoring\n const lockDuration = mutex.lockTime ? Date.now() - mutex.lockTime : 0;\n \n // Atomic release with state validation\n mutex.locked = false;\n mutex.lockId = null;\n mutex.lockTime = null;\n \n this._secureLog('debug', `\uD83D\uDD13 Mutex released successfully: ${mutexName}`, {\n operationId: operationId,\n lockDuration: lockDuration,\n queueLength: mutex.queue.length\n });\n \n // Process next in queue with enhanced error handling\n this._processNextInQueue(mutexName);\n \n } catch (error) {\n // If queue processing fails, ensure mutex is still released\n this._secureLog('error', `\u274C Error during mutex release queue processing`, {\n mutexName: mutexName,\n operationId: operationId,\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n \n // Ensure mutex is released even if queue processing fails\n mutex.locked = false;\n mutex.lockId = null;\n mutex.lockTime = null;\n mutex.lockTimeout = null;\n \n throw error;\n }\n }\n\n /**\n * Enhanced queue processing with comprehensive error handling\n */\n _processNextInQueue(mutexName) {\n const mutex = this[`_${mutexName}Mutex`];\n \n if (!mutex) {\n this._secureLog('error', `\u274C Mutex not found for queue processing: ${mutexName}`);\n return;\n }\n \n if (mutex.queue.length === 0) {\n return;\n }\n \n // Validate mutex state before processing queue\n if (mutex.locked) {\n this._secureLog('warn', `\u26A0\uFE0F Mutex '${mutexName}' is still locked, skipping queue processing`, {\n lockId: mutex.lockId,\n queueLength: mutex.queue.length\n });\n return;\n }\n \n // Get next item from queue atomically with validation\n const nextItem = mutex.queue.shift();\n \n if (!nextItem) {\n this._secureLog('warn', `\u26A0\uFE0F Empty queue item for mutex '${mutexName}'`);\n return;\n }\n \n // Validate queue item structure\n if (!nextItem.operationId || !nextItem.resolve || !nextItem.reject) {\n this._secureLog('error', `\u274C Invalid queue item structure for mutex '${mutexName}'`, {\n hasOperationId: !!nextItem.operationId,\n hasResolve: !!nextItem.resolve,\n hasReject: !!nextItem.reject\n });\n return;\n }\n \n try {\n // Clear timeout for this item\n if (nextItem.timeout) {\n clearTimeout(nextItem.timeout);\n }\n \n // Attempt to acquire lock for next item\n this._secureLog('debug', `\uD83D\uDD04 Processing next operation in queue for mutex '${mutexName}'`, {\n operationId: nextItem.operationId,\n queueRemaining: mutex.queue.length,\n timestamp: Date.now()\n });\n \n // Retry lock acquisition for queued operation with enhanced error handling\n setTimeout(async () => {\n try {\n await this._acquireMutex(mutexName, nextItem.operationId, 5000);\n \n this._secureLog('debug', `\u2705 Queued operation acquired mutex '${mutexName}'`, {\n operationId: nextItem.operationId,\n acquisitionTime: Date.now()\n });\n \n nextItem.resolve();\n \n } catch (error) {\n this._secureLog('error', `\u274C Queued operation failed to acquire mutex '${mutexName}'`, {\n operationId: nextItem.operationId,\n errorType: error.constructor.name,\n errorMessage: error.message,\n timestamp: Date.now()\n });\n \n // Reject with detailed error information\n nextItem.reject(new Error(`Queue processing failed for '${mutexName}': ${error.message}`));\n \n // Continue processing queue even if one item fails\n setTimeout(() => {\n this._processNextInQueue(mutexName);\n }, 50);\n }\n }, 10); // Small delay to prevent immediate re-acquisition\n \n } catch (error) {\n this._secureLog('error', `\u274C Critical error during queue processing for mutex '${mutexName}'`, {\n operationId: nextItem.operationId,\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n \n // Reject the operation and continue processing\n try {\n nextItem.reject(new Error(`Queue processing critical error: ${error.message}`));\n } catch (rejectError) {\n this._secureLog('error', `\u274C Failed to reject queue item`, {\n originalError: error.message,\n rejectError: rejectError.message\n });\n }\n \n // Continue processing remaining queue items\n setTimeout(() => {\n this._processNextInQueue(mutexName);\n }, 100);\n }\n }\n\n _getAvailableMutexes() {\n const mutexes = [];\n const propertyNames = Object.getOwnPropertyNames(this);\n \n for (const prop of propertyNames) {\n if (prop.endsWith('Mutex') && prop.startsWith('_')) {\n // Extract mutex name without prefix/suffix\n const mutexName = prop.slice(1, -5); // Remove '_' prefix and 'Mutex' suffix\n mutexes.push(mutexName);\n }\n }\n \n return mutexes;\n }\n\n /**\n * Enhanced mutex execution with atomic operations\n */\n async _withMutex(mutexName, operation, timeout = 5000) {\n const operationId = this._generateOperationId();\n \n // Validate mutex system before operation\n if (!this._validateMutexSystem()) {\n this._secureLog('error', '\u274C Mutex system not properly initialized', {\n operationId: operationId,\n mutexName: mutexName\n });\n throw new Error('Mutex system not properly initialized. Call _initializeMutexSystem() first.');\n }\n \n // Get mutex reference with validation\n const mutex = this[`_${mutexName}Mutex`];\n if (!mutex) {\n throw new Error(`Mutex '${mutexName}' not found`);\n }\n \n let mutexAcquired = false;\n \n try {\n // Atomic mutex acquisition with timeout\n await this._acquireMutex(mutexName, operationId, timeout);\n mutexAcquired = true;\n \n // Increment operation counter atomically\n const counterKey = `${mutexName}Operations`;\n if (this._operationCounters && this._operationCounters[counterKey] !== undefined) {\n this._operationCounters[counterKey]++;\n }\n \n // Execute operation with enhanced error handling\n const result = await operation(operationId);\n \n // Validate result before returning\n if (result === undefined && operation.name !== 'cleanup') {\n this._secureLog('warn', '\u26A0\uFE0F Mutex operation returned undefined result', {\n operationId: operationId,\n mutexName: mutexName,\n operationName: operation.name\n });\n }\n \n return result;\n \n } catch (error) {\n // Enhanced error logging with context\n this._secureLog('error', '\u274C Error in mutex operation', {\n operationId: operationId,\n mutexName: mutexName,\n errorType: error.constructor.name,\n errorMessage: error.message,\n mutexAcquired: mutexAcquired,\n mutexState: mutex ? {\n locked: mutex.locked,\n lockId: mutex.lockId,\n queueLength: mutex.queue.length\n } : 'null'\n });\n \n // If this is a key operation error, trigger emergency recovery\n if (mutexName === 'keyOperation') {\n this._handleKeyOperationError(error, operationId);\n }\n \n // Trigger emergency unlock for critical mutex errors\n if (error.message.includes('timeout') || error.message.includes('race condition')) {\n this._emergencyUnlockAllMutexes('errorHandler');\n }\n \n throw error;\n } finally {\n // Always release mutex in finally block with validation\n if (mutexAcquired) {\n try {\n await this._releaseMutex(mutexName, operationId);\n \n // Verify mutex was properly released\n if (mutex.locked && mutex.lockId === operationId) {\n this._secureLog('error', '\u274C Mutex release verification failed', {\n operationId: operationId,\n mutexName: mutexName\n });\n // Force release as fallback\n mutex.locked = false;\n mutex.lockId = null;\n mutex.lockTimeout = null;\n }\n \n } catch (releaseError) {\n this._secureLog('error', '\u274C Error releasing mutex in finally block', {\n operationId: operationId,\n mutexName: mutexName,\n releaseErrorType: releaseError.constructor.name,\n releaseErrorMessage: releaseError.message\n });\n \n // Force release on error\n mutex.locked = false;\n mutex.lockId = null;\n mutex.lockTimeout = null;\n }\n }\n }\n }\n\n _validateMutexSystem() {\n const requiredMutexes = ['keyOperation', 'cryptoOperation', 'connectionOperation'];\n \n for (const mutexName of requiredMutexes) {\n const mutexPropertyName = `_${mutexName}Mutex`;\n const mutex = this[mutexPropertyName];\n \n if (!mutex || typeof mutex !== 'object') {\n this._secureLog('error', `\u274C Missing or invalid mutex: ${mutexName}`, {\n mutexPropertyName: mutexPropertyName,\n mutexType: typeof mutex\n });\n return false;\n }\n \n // Validate mutex structure\n const requiredProps = ['locked', 'queue', 'lockId', 'lockTimeout'];\n for (const prop of requiredProps) {\n if (!(prop in mutex)) {\n this._secureLog('error', `\u274C Mutex ${mutexName} missing property: ${prop}`);\n return false;\n }\n }\n }\n \n return true;\n }\n\n /**\n * Enhanced emergency recovery of the mutex system\n */\n _emergencyRecoverMutexSystem() {\n this._secureLog('warn', '\uD83D\uDEA8 Emergency mutex system recovery initiated');\n \n try {\n // Emergency unlock all mutexes first\n this._emergencyUnlockAllMutexes('emergencyRecovery');\n \n // Force re-initialize the system\n this._initializeMutexSystem();\n \n // Validate recovery success\n if (!this._validateMutexSystem()) {\n throw new Error('Mutex system validation failed after recovery');\n }\n \n this._secureLog('info', '\u2705 Mutex system recovered successfully with validation');\n return true;\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to recover mutex system', {\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n \n // Last resort - force re-initialization\n try {\n this._initializeMutexSystem();\n this._secureLog('warn', '\u26A0\uFE0F Forced mutex system re-initialization completed');\n return true;\n } catch (reinitError) {\n this._secureLog('error', '\u274C CRITICAL: Forced re-initialization also failed', {\n originalError: error.message,\n reinitError: reinitError.message\n });\n return false;\n }\n }\n }\n\n /**\n * Atomic key generation with race condition protection\n */\n async _generateEncryptionKeys() {\n return this._withMutex('keyOperation', async (operationId) => {\n this._secureLog('info', '\uD83D\uDD11 Generating encryption keys with atomic mutex', {\n operationId: operationId\n });\n \n // Atomic state check and update using mutex lock\n const currentState = this._keySystemState;\n \n // Atomic check - if already initializing, wait or fail\n if (currentState.isInitializing) {\n this._secureLog('warn', '\u26A0\uFE0F Key generation already in progress, waiting for completion', {\n operationId: operationId,\n lastOperation: currentState.lastOperation,\n lastOperationTime: currentState.lastOperationTime\n });\n \n // Wait for existing operation to complete\n let waitAttempts = 0;\n const maxWaitAttempts = 50; // 5 seconds max wait\n \n while (currentState.isInitializing && waitAttempts < maxWaitAttempts) {\n await new Promise(resolve => setTimeout(resolve, 100));\n waitAttempts++;\n }\n \n if (currentState.isInitializing) {\n throw new Error('Key generation timeout - operation still in progress after 5 seconds');\n }\n }\n \n // Atomic state update within mutex protection\n try {\n // Set state atomically within mutex\n currentState.isInitializing = true;\n currentState.lastOperation = 'generation';\n currentState.lastOperationTime = Date.now();\n currentState.operationId = operationId;\n \n this._secureLog('debug', '\uD83D\uDD12 Atomic key generation state set', {\n operationId: operationId,\n timestamp: currentState.lastOperationTime\n });\n \n // Generate keys with individual error handling\n let ecdhKeyPair = null;\n let ecdsaKeyPair = null;\n \n // Generate ephemeral ECDH keys for PFS\n try {\n ecdhKeyPair = await this._generateEphemeralECDHKeys();\n \n // Validate ECDH keys immediately\n if (!ecdhKeyPair || !ecdhKeyPair.privateKey || !ecdhKeyPair.publicKey) {\n throw new Error('Ephemeral ECDH key pair validation failed');\n }\n \n // Constant-time validation for key types\n if (!this._validateKeyPairConstantTime(ecdhKeyPair)) {\n throw new Error('Ephemeral ECDH keys are not valid CryptoKey instances');\n }\n \n this._secureLog('debug', '\u2705 Ephemeral ECDH keys generated and validated for PFS', {\n operationId: operationId,\n privateKeyType: ecdhKeyPair.privateKey.algorithm?.name,\n publicKeyType: ecdhKeyPair.publicKey.algorithm?.name,\n isEphemeral: true\n });\n \n } catch (ecdhError) {\n this._secureLog('error', '\u274C Ephemeral ECDH key generation failed', {\n operationId: operationId,\n errorType: ecdhError.constructor.name\n });\n this._throwSecureError(ecdhError, 'ephemeral_ecdh_key_generation');\n }\n \n // Generate ECDSA keys with retry mechanism\n try {\n ecdsaKeyPair = await window.EnhancedSecureCryptoUtils.generateECDSAKeyPair();\n \n // Validate ECDSA keys immediately\n if (!ecdsaKeyPair || !ecdsaKeyPair.privateKey || !ecdsaKeyPair.publicKey) {\n throw new Error('ECDSA key pair validation failed');\n }\n \n // Constant-time validation for key types\n if (!this._validateKeyPairConstantTime(ecdsaKeyPair)) {\n throw new Error('ECDSA keys are not valid CryptoKey instances');\n }\n \n this._secureLog('debug', '\u2705 ECDSA keys generated and validated', {\n operationId: operationId,\n privateKeyType: ecdsaKeyPair.privateKey.algorithm?.name,\n publicKeyType: ecdsaKeyPair.publicKey.algorithm?.name\n });\n \n } catch (ecdsaError) {\n this._secureLog('error', '\u274C ECDSA key generation failed', {\n operationId: operationId,\n errorType: ecdsaError.constructor.name\n });\n this._throwSecureError(ecdsaError, 'ecdsa_key_generation');\n }\n \n // Final validation of both key pairs\n if (!ecdhKeyPair || !ecdsaKeyPair) {\n throw new Error('One or both key pairs failed to generate');\n }\n \n // Enable security features after successful key generation\n this._enableSecurityFeaturesAfterKeyGeneration(ecdhKeyPair, ecdsaKeyPair);\n \n this._secureLog('info', '\u2705 Encryption keys generated successfully with atomic protection', {\n operationId: operationId,\n hasECDHKeys: !!(ecdhKeyPair?.privateKey && ecdhKeyPair?.publicKey),\n hasECDSAKeys: !!(ecdsaKeyPair?.privateKey && ecdsaKeyPair?.publicKey),\n generationTime: Date.now() - currentState.lastOperationTime\n });\n \n return { ecdhKeyPair, ecdsaKeyPair };\n \n } catch (error) {\n // Ensure state is reset on any error\n this._secureLog('error', '\u274C Key generation failed, resetting state', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n throw error;\n } finally {\n // Always reset state in finally block\n currentState.isInitializing = false;\n currentState.operationId = null;\n \n this._secureLog('debug', '\uD83D\uDD13 Key generation state reset', {\n operationId: operationId\n });\n }\n });\n }\n\n /**\n * Enable security features after successful key generation\n */\n _enableSecurityFeaturesAfterKeyGeneration(ecdhKeyPair, ecdsaKeyPair) {\n try {\n // Enable encryption features based on available keys\n if (ecdhKeyPair && ecdhKeyPair.privateKey && ecdhKeyPair.publicKey) {\n this.securityFeatures.hasEncryption = true;\n this.securityFeatures.hasECDH = true;\n this._secureLog('info', '\uD83D\uDD12 ECDH encryption features enabled');\n }\n \n if (ecdsaKeyPair && ecdsaKeyPair.privateKey && ecdsaKeyPair.publicKey) {\n this.securityFeatures.hasECDSA = true;\n this._secureLog('info', '\uD83D\uDD12 ECDSA signature features enabled');\n }\n \n // Enable additional features that depend on encryption\n if (this.securityFeatures.hasEncryption) {\n this.securityFeatures.hasMetadataProtection = true;\n this.securityFeatures.hasEnhancedReplayProtection = true;\n this.securityFeatures.hasNonExtractableKeys = true;\n this._secureLog('info', '\uD83D\uDD12 Additional encryption-dependent features enabled');\n }\n \n // Enable PFS after ephemeral key generation\n if (ecdhKeyPair && this.ephemeralKeyPairs.size > 0) {\n this.securityFeatures.hasPFS = true;\n this._secureLog('info', '\uD83D\uDD12 Perfect Forward Secrecy enabled with ephemeral keys');\n }\n \n this._secureLog('info', '\uD83D\uDD12 Security features updated after key generation', {\n hasEncryption: this.securityFeatures.hasEncryption,\n hasECDH: this.securityFeatures.hasECDH,\n hasECDSA: this.securityFeatures.hasECDSA,\n hasMetadataProtection: this.securityFeatures.hasMetadataProtection,\n hasEnhancedReplayProtection: this.securityFeatures.hasEnhancedReplayProtection,\n hasNonExtractableKeys: this.securityFeatures.hasNonExtractableKeys,\n hasPFS: this.securityFeatures.hasPFS\n });\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to enable security features after key generation', {\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n }\n }\n\n /**\n * Enhanced emergency mutex unlocking with authorization and validation\n */\n _emergencyUnlockAllMutexes(callerContext = 'unknown') {\n // Validate caller authorization\n const authorizedCallers = [\n 'keyOperation', 'cryptoOperation', 'connectionOperation',\n 'emergencyRecovery', 'systemShutdown', 'errorHandler'\n ];\n \n if (!authorizedCallers.includes(callerContext)) {\n this._secureLog('error', `\uD83D\uDEA8 UNAUTHORIZED emergency mutex unlock attempt`, {\n callerContext: callerContext,\n authorizedCallers: authorizedCallers,\n timestamp: Date.now()\n });\n throw new Error(`Unauthorized emergency mutex unlock attempt by: ${callerContext}`);\n }\n \n const mutexes = ['keyOperation', 'cryptoOperation', 'connectionOperation'];\n \n this._secureLog('error', '\uD83D\uDEA8 EMERGENCY: Unlocking all mutexes with authorization and state cleanup', {\n callerContext: callerContext,\n timestamp: Date.now()\n });\n \n let unlockedCount = 0;\n let errorCount = 0;\n \n mutexes.forEach(mutexName => {\n const mutex = this[`_${mutexName}Mutex`];\n if (mutex) {\n try {\n // Clear timeout first\n if (mutex.lockTimeout) {\n clearTimeout(mutex.lockTimeout);\n }\n \n // Log mutex state before emergency unlock\n const previousState = {\n locked: mutex.locked,\n lockId: mutex.lockId,\n lockTime: mutex.lockTime,\n queueLength: mutex.queue.length\n };\n \n // Reset mutex state atomically\n mutex.locked = false;\n mutex.lockId = null;\n mutex.lockTimeout = null;\n mutex.lockTime = null;\n \n // Clear queue with proper error handling and logging\n let queueRejectCount = 0;\n mutex.queue.forEach(item => {\n try {\n if (item.reject && typeof item.reject === 'function') {\n item.reject(new Error(`Emergency mutex unlock for ${mutexName} by ${callerContext}`));\n queueRejectCount++;\n }\n } catch (rejectError) {\n this._secureLog('warn', `\u26A0\uFE0F Failed to reject queue item during emergency unlock`, {\n mutexName: mutexName,\n errorType: rejectError.constructor.name\n });\n }\n });\n \n // Clear queue array\n mutex.queue = [];\n \n unlockedCount++;\n \n this._secureLog('debug', `\uD83D\uDD13 Emergency unlocked mutex: ${mutexName}`, {\n previousState: previousState,\n queueRejectCount: queueRejectCount,\n callerContext: callerContext\n });\n \n } catch (error) {\n errorCount++;\n this._secureLog('error', `\u274C Error during emergency unlock of mutex: ${mutexName}`, {\n errorType: error.constructor.name,\n errorMessage: error.message,\n callerContext: callerContext\n });\n }\n }\n });\n \n // Reset key system state with validation\n if (this._keySystemState) {\n try {\n const previousKeyState = { ...this._keySystemState };\n \n this._keySystemState.isInitializing = false;\n this._keySystemState.isRotating = false;\n this._keySystemState.isDestroying = false;\n this._keySystemState.operationId = null;\n this._keySystemState.concurrentOperations = 0;\n \n this._secureLog('debug', `\uD83D\uDD13 Emergency reset key system state`, {\n previousState: previousKeyState,\n callerContext: callerContext\n });\n \n } catch (error) {\n this._secureLog('error', `\u274C Error resetting key system state during emergency unlock`, {\n errorType: error.constructor.name,\n errorMessage: error.message,\n callerContext: callerContext\n });\n }\n }\n \n // Log emergency unlock summary\n this._secureLog('info', `\uD83D\uDEA8 Emergency mutex unlock completed`, {\n callerContext: callerContext,\n unlockedCount: unlockedCount,\n errorCount: errorCount,\n totalMutexes: mutexes.length,\n timestamp: Date.now()\n });\n \n // Trigger system validation after emergency unlock\n setTimeout(() => {\n this._validateMutexSystemAfterEmergencyUnlock();\n }, 100);\n }\n\n /**\n * Handle key operation errors with recovery mechanisms\n */\n _handleKeyOperationError(error, operationId) {\n this._secureLog('error', '\uD83D\uDEA8 Key operation error detected, initiating recovery', {\n operationId: operationId,\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n \n // Reset key system state immediately\n if (this._keySystemState) {\n this._keySystemState.isInitializing = false;\n this._keySystemState.isRotating = false;\n this._keySystemState.isDestroying = false;\n this._keySystemState.operationId = null;\n }\n \n // Clear any partial key data\n this.ecdhKeyPair = null;\n this.ecdsaKeyPair = null;\n this.encryptionKey = null;\n this.macKey = null;\n this.metadataKey = null;\n \n // Trigger emergency recovery if needed\n if (error.message.includes('timeout') || error.message.includes('race condition')) {\n this._secureLog('warn', '\u26A0\uFE0F Race condition or timeout detected, triggering emergency recovery');\n this._emergencyRecoverMutexSystem();\n }\n }\n\n /**\n * Generate cryptographically secure IV with reuse prevention\n */\n _generateSecureIV(ivSize = 12, context = 'general') {\n // Check if we're in emergency mode\n if (this._ivTrackingSystem.emergencyMode) {\n this._secureLog('error', '\uD83D\uDEA8 CRITICAL: IV generation blocked - emergency mode active due to IV reuse');\n throw new Error('IV generation blocked - emergency mode active');\n }\n \n let attempts = 0;\n const maxAttempts = 100; // Prevent infinite loops\n \n while (attempts < maxAttempts) {\n attempts++;\n \n // Generate fresh IV with crypto.getRandomValues\n const iv = crypto.getRandomValues(new Uint8Array(ivSize));\n \n // Convert IV to string for tracking\n const ivString = Array.from(iv).map(b => b.toString(16).padStart(2, '0')).join('');\n \n // Check for IV reuse\n if (this._ivTrackingSystem.usedIVs.has(ivString)) {\n this._ivTrackingSystem.collisionCount++;\n this._secureLog('error', `\uD83D\uDEA8 CRITICAL: IV reuse detected!`, {\n context: context,\n attempt: attempts,\n collisionCount: this._ivTrackingSystem.collisionCount,\n ivString: ivString.substring(0, 16) + '...' // Log partial IV for debugging\n });\n \n // If too many collisions, trigger emergency mode\n if (this._ivTrackingSystem.collisionCount > 5) {\n this._ivTrackingSystem.emergencyMode = true;\n this._secureLog('error', '\uD83D\uDEA8 CRITICAL: Emergency mode activated due to excessive IV reuse');\n throw new Error('Emergency mode: Excessive IV reuse detected');\n }\n \n continue; // Try again\n }\n \n // Validate IV entropy\n if (!this._validateIVEntropy(iv)) {\n this._ivTrackingSystem.entropyValidation.entropyFailures++;\n this._secureLog('warn', `\u26A0\uFE0F Low entropy IV detected`, {\n context: context,\n attempt: attempts,\n entropyFailures: this._ivTrackingSystem.entropyValidation.entropyFailures\n });\n \n // If too many entropy failures, trigger emergency mode\n if (this._ivTrackingSystem.entropyValidation.entropyFailures > 10) {\n this._ivTrackingSystem.emergencyMode = true;\n this._secureLog('error', '\uD83D\uDEA8 CRITICAL: Emergency mode activated due to low entropy IVs');\n throw new Error('Emergency mode: Low entropy IVs detected');\n }\n \n continue; // Try again\n }\n \n // Track IV usage\n this._ivTrackingSystem.usedIVs.add(ivString);\n this._ivTrackingSystem.ivHistory.set(ivString, {\n timestamp: Date.now(),\n context: context,\n attempt: attempts\n });\n \n // Track per-session IVs\n if (this.sessionId) {\n if (!this._ivTrackingSystem.sessionIVs.has(this.sessionId)) {\n this._ivTrackingSystem.sessionIVs.set(this.sessionId, new Set());\n }\n this._ivTrackingSystem.sessionIVs.get(this.sessionId).add(ivString);\n }\n \n // Validate RNG periodically\n this._validateRNGQuality();\n \n this._secureLog('debug', `\u2705 Secure IV generated`, {\n context: context,\n attempt: attempts,\n ivSize: ivSize,\n totalIVs: this._ivTrackingSystem.usedIVs.size\n });\n \n return iv;\n }\n \n // If we can't generate a unique IV after max attempts\n this._secureLog('error', `\u274C Failed to generate unique IV after ${maxAttempts} attempts`, {\n context: context,\n totalIVs: this._ivTrackingSystem.usedIVs.size\n });\n throw new Error(`Failed to generate unique IV after ${maxAttempts} attempts`);\n }\n \n /**\n * Validate IV entropy to detect weak RNG\n */\n _validateIVEntropy(iv) {\n this._ivTrackingSystem.entropyValidation.entropyTests++;\n \n // Calculate byte distribution\n const byteCounts = new Array(256).fill(0);\n for (let i = 0; i < iv.length; i++) {\n byteCounts[iv[i]]++;\n }\n \n // Multi-dimensional entropy analysis\n const entropyResults = {\n shannon: 0,\n min: 0,\n collision: 0,\n compression: 0,\n quantum: 0\n };\n \n // 1. Shannon entropy calculation\n let shannonEntropy = 0;\n const totalBytes = iv.length;\n \n for (let i = 0; i < 256; i++) {\n if (byteCounts[i] > 0) {\n const probability = byteCounts[i] / totalBytes;\n shannonEntropy -= probability * Math.log2(probability);\n }\n }\n entropyResults.shannon = shannonEntropy;\n \n // 2. Min-entropy calculation (worst-case scenario)\n const maxCount = Math.max(...byteCounts);\n const maxProbability = maxCount / totalBytes;\n entropyResults.min = -Math.log2(maxProbability);\n \n // 3. Collision entropy calculation\n let collisionSum = 0;\n for (let i = 0; i < 256; i++) {\n if (byteCounts[i] > 0) {\n const probability = byteCounts[i] / totalBytes;\n collisionSum += probability * probability;\n }\n }\n entropyResults.collision = -Math.log2(collisionSum);\n \n // 4. Compression-based entropy estimation\n const ivString = Array.from(iv).map(b => String.fromCharCode(b)).join('');\n const compressedLength = this._estimateCompressedLength(ivString);\n entropyResults.compression = (1 - compressedLength / totalBytes) * 8;\n \n // 5. Quantum-resistant entropy analysis\n entropyResults.quantum = this._calculateQuantumResistantEntropy(iv);\n \n // Enhanced suspicious pattern detection\n const hasSuspiciousPatterns = this._detectAdvancedSuspiciousPatterns(iv);\n \n // Multi-criteria validation\n const minEntropyThreshold = this._ivTrackingSystem.entropyValidation.minEntropy;\n const isValid = (\n entropyResults.shannon >= minEntropyThreshold &&\n entropyResults.min >= minEntropyThreshold * 0.8 &&\n entropyResults.collision >= minEntropyThreshold * 0.9 &&\n entropyResults.compression >= minEntropyThreshold * 0.7 &&\n entropyResults.quantum >= minEntropyThreshold * 0.6 &&\n !hasSuspiciousPatterns\n );\n \n if (!isValid) {\n this._secureLog('warn', `\u26A0\uFE0F Enhanced IV entropy validation failed`, {\n shannon: entropyResults.shannon.toFixed(2),\n min: entropyResults.min.toFixed(2),\n collision: entropyResults.collision.toFixed(2),\n compression: entropyResults.compression.toFixed(2),\n quantum: entropyResults.quantum.toFixed(2),\n minThreshold: minEntropyThreshold,\n hasSuspiciousPatterns: hasSuspiciousPatterns\n });\n }\n \n return isValid;\n }\n \n /**\n * Estimate compressed length for entropy calculation\n * @param {string} data - Data to estimate compression\n * @returns {number} Estimated compressed length\n */\n _estimateCompressedLength(data) {\n // Simple LZ77-like compression estimation\n let compressedLength = 0;\n let i = 0;\n \n while (i < data.length) {\n let matchLength = 0;\n let matchDistance = 0;\n \n // Look for repeated patterns\n for (let j = Math.max(0, i - 255); j < i; j++) {\n let k = 0;\n while (i + k < data.length && data[i + k] === data[j + k] && k < 255) {\n k++;\n }\n if (k > matchLength) {\n matchLength = k;\n matchDistance = i - j;\n }\n }\n \n if (matchLength >= 3) {\n compressedLength += 3; // Distance + length + literal\n i += matchLength;\n } else {\n compressedLength += 1;\n i += 1;\n }\n }\n \n return compressedLength;\n }\n\n /**\n * Calculate quantum-resistant entropy\n * @param {Uint8Array} data - Data to analyze\n * @returns {number} Quantum-resistant entropy score\n */\n _calculateQuantumResistantEntropy(data) {\n // Quantum-resistant entropy analysis\n let quantumScore = 0;\n \n // 1. Check for quantum-vulnerable patterns\n const hasQuantumVulnerablePatterns = this._detectQuantumVulnerablePatterns(data);\n if (hasQuantumVulnerablePatterns) {\n quantumScore -= 2;\n }\n \n // 2. Analyze bit distribution\n const bitDistribution = this._analyzeBitDistribution(data);\n quantumScore += bitDistribution.score;\n \n // 3. Check for periodicity\n const periodicity = this._detectPeriodicity(data);\n quantumScore -= periodicity * 0.5;\n \n // 4. Normalize to 0-8 range\n return Math.max(0, Math.min(8, quantumScore));\n }\n\n /**\n * Detect quantum-vulnerable patterns\n * @param {Uint8Array} data - Data to analyze\n * @returns {boolean} true if quantum-vulnerable patterns found\n */\n _detectQuantumVulnerablePatterns(data) {\n // Check for patterns vulnerable to quantum attacks\n const patterns = [\n [0, 0, 0, 0, 0, 0, 0, 0], // All zeros\n [255, 255, 255, 255, 255, 255, 255, 255], // All ones\n [0, 1, 0, 1, 0, 1, 0, 1], // Alternating\n [1, 0, 1, 0, 1, 0, 1, 0] // Alternating reverse\n ];\n \n for (const pattern of patterns) {\n for (let i = 0; i <= data.length - pattern.length; i++) {\n let match = true;\n for (let j = 0; j < pattern.length; j++) {\n if (data[i + j] !== pattern[j]) {\n match = false;\n break;\n }\n }\n if (match) return true;\n }\n }\n \n return false;\n }\n\n /**\n * Analyze bit distribution\n * @param {Uint8Array} data - Data to analyze\n * @returns {Object} Bit distribution analysis\n */\n _analyzeBitDistribution(data) {\n let ones = 0;\n let totalBits = data.length * 8;\n \n for (const byte of data) {\n ones += (byte >>> 0).toString(2).split('1').length - 1;\n }\n \n const zeroRatio = (totalBits - ones) / totalBits;\n const oneRatio = ones / totalBits;\n \n // Ideal distribution is 50/50\n const deviation = Math.abs(0.5 - oneRatio);\n const score = Math.max(0, 8 - deviation * 16);\n \n return { score, zeroRatio, oneRatio, deviation };\n }\n\n /**\n * Detect periodicity in data\n * @param {Uint8Array} data - Data to analyze\n * @returns {number} Periodicity score (0-1)\n */\n _detectPeriodicity(data) {\n if (data.length < 16) return 0;\n \n let maxPeriodicity = 0;\n \n // Check for periods from 2 to data.length/2\n for (let period = 2; period <= data.length / 2; period++) {\n let matches = 0;\n let totalChecks = 0;\n \n for (let i = 0; i < data.length - period; i++) {\n if (data[i] === data[i + period]) {\n matches++;\n }\n totalChecks++;\n }\n \n if (totalChecks > 0) {\n const periodicity = matches / totalChecks;\n maxPeriodicity = Math.max(maxPeriodicity, periodicity);\n }\n }\n \n return maxPeriodicity;\n }\n\n /**\n * Enhanced suspicious pattern detection\n * @param {Uint8Array} iv - IV to check\n * @returns {boolean} true if suspicious patterns found\n */\n _detectAdvancedSuspiciousPatterns(iv) {\n // Enhanced pattern detection with quantum-resistant analysis\n const patterns = [\n // Sequential patterns\n [0, 1, 2, 3, 4, 5, 6, 7],\n [255, 254, 253, 252, 251, 250, 249, 248],\n \n // Repeated patterns\n [0, 0, 0, 0, 0, 0, 0, 0],\n [255, 255, 255, 255, 255, 255, 255, 255],\n \n // Alternating patterns\n [0, 255, 0, 255, 0, 255, 0, 255],\n [255, 0, 255, 0, 255, 0, 255, 0]\n ];\n \n for (const pattern of patterns) {\n for (let i = 0; i <= iv.length - pattern.length; i++) {\n let match = true;\n for (let j = 0; j < pattern.length; j++) {\n if (iv[i + j] !== pattern[j]) {\n match = false;\n break;\n }\n }\n if (match) return true;\n }\n }\n \n // Check for low entropy regions\n const entropyMap = this._calculateLocalEntropy(iv);\n const lowEntropyRegions = entropyMap.filter(e => e < 3.0).length;\n \n return lowEntropyRegions > iv.length * 0.3; // More than 30% low entropy\n }\n\n /**\n * Calculate local entropy for pattern detection\n * @param {Uint8Array} data - Data to analyze\n * @returns {Array} Array of local entropy values\n */\n _calculateLocalEntropy(data) {\n const windowSize = 8;\n const entropyMap = [];\n \n for (let i = 0; i <= data.length - windowSize; i++) {\n const window = data.slice(i, i + windowSize);\n const charCount = {};\n \n for (const byte of window) {\n charCount[byte] = (charCount[byte] || 0) + 1;\n }\n \n let entropy = 0;\n for (const count of Object.values(charCount)) {\n const probability = count / windowSize;\n entropy -= probability * Math.log2(probability);\n }\n \n entropyMap.push(entropy);\n }\n \n return entropyMap;\n }\n\n /**\n * Detect suspicious patterns in IVs\n */\n _detectSuspiciousIVPatterns(iv) {\n // Check for all zeros or all ones\n const allZeros = iv.every(byte => byte === 0);\n const allOnes = iv.every(byte => byte === 255);\n \n if (allZeros || allOnes) {\n return true;\n }\n \n // Check for sequential patterns\n let sequentialCount = 0;\n for (let i = 1; i < iv.length; i++) {\n if (iv[i] === iv[i-1] + 1 || iv[i] === iv[i-1] - 1) {\n sequentialCount++;\n } else {\n sequentialCount = 0;\n }\n \n if (sequentialCount >= 3) {\n return true; // Suspicious sequential pattern\n }\n }\n \n // Check for repeated patterns\n for (let patternLength = 2; patternLength <= Math.floor(iv.length / 2); patternLength++) {\n for (let start = 0; start <= iv.length - patternLength * 2; start++) {\n const pattern1 = iv.slice(start, start + patternLength);\n const pattern2 = iv.slice(start + patternLength, start + patternLength * 2);\n \n if (pattern1.every((byte, index) => byte === pattern2[index])) {\n return true; // Repeated pattern detected\n }\n }\n }\n \n return false;\n }\n \n /**\n * Clean up old IVs with strict limits\n */\n _cleanupOldIVs() {\n const now = Date.now();\n const maxAge = 1800000; // Reduced to 30 minutes for better security\n let cleanedCount = 0;\n const cleanupBatch = [];\n \n // Aggressive cleanup with quantum-resistant patterns\n // Enforce maximum IV history size with batch processing\n if (this._ivTrackingSystem.ivHistory.size > this._ivTrackingSystem.maxIVHistorySize) {\n const ivArray = Array.from(this._ivTrackingSystem.ivHistory.entries());\n const toRemove = ivArray.slice(0, ivArray.length - this._ivTrackingSystem.maxIVHistorySize);\n \n for (const [ivString] of toRemove) {\n cleanupBatch.push(ivString);\n cleanedCount++;\n \n // Process in batches to prevent memory spikes\n if (cleanupBatch.length >= 100) {\n this._processCleanupBatch(cleanupBatch);\n cleanupBatch.length = 0;\n }\n }\n }\n \n // Clean up old IVs from history by age with enhanced security\n for (const [ivString, metadata] of this._ivTrackingSystem.ivHistory.entries()) {\n if (now - metadata.timestamp > maxAge) {\n cleanupBatch.push(ivString);\n cleanedCount++;\n \n // Process in batches to prevent memory spikes\n if (cleanupBatch.length >= 100) {\n this._processCleanupBatch(cleanupBatch);\n cleanupBatch.length = 0;\n }\n }\n }\n \n // Process remaining batch\n if (cleanupBatch.length > 0) {\n this._processCleanupBatch(cleanupBatch);\n }\n \n // Enhanced session IV cleanup with entropy preservation\n for (const [sessionId, sessionIVs] of this._ivTrackingSystem.sessionIVs.entries()) {\n if (sessionIVs.size > this._ivTrackingSystem.maxSessionIVs) {\n const ivArray = Array.from(sessionIVs);\n const toRemove = ivArray.slice(0, ivArray.length - this._ivTrackingSystem.maxSessionIVs);\n \n for (const ivString of toRemove) {\n sessionIVs.delete(ivString);\n this._ivTrackingSystem.usedIVs.delete(ivString);\n this._ivTrackingSystem.ivHistory.delete(ivString);\n cleanedCount++;\n }\n }\n }\n \n // Force garbage collection if available and significant cleanup occurred\n if (typeof window.gc === 'function' && cleanedCount > 50) {\n try {\n window.gc();\n } catch (e) {\n // Ignore GC errors\n }\n }\n \n if (cleanedCount > 0) {\n this._secureLog('debug', `\uD83E\uDDF9 Enhanced cleanup: ${cleanedCount} old IVs removed`, {\n cleanedCount: cleanedCount,\n remainingIVs: this._ivTrackingSystem.usedIVs.size,\n remainingHistory: this._ivTrackingSystem.ivHistory.size,\n memoryPressure: this._calculateMemoryPressure()\n });\n }\n }\n \n /**\n * Process cleanup batch with constant-time operations\n * @param {Array} batch - Batch of items to clean up\n */\n _processCleanupBatch(batch) {\n // Constant-time batch processing\n for (const item of batch) {\n this._ivTrackingSystem.usedIVs.delete(item);\n this._ivTrackingSystem.ivHistory.delete(item);\n }\n }\n\n /**\n * Calculate memory pressure for adaptive cleanup\n * @returns {number} Memory pressure score (0-100)\n */\n _calculateMemoryPressure() {\n const totalIVs = this._ivTrackingSystem.usedIVs.size;\n const maxAllowed = this._resourceLimits.maxIVHistory;\n \n return Math.min(100, Math.floor((totalIVs / maxAllowed) * 100));\n }\n\n /**\n * Get IV tracking system statistics\n */\n _getIVTrackingStats() {\n return {\n totalIVs: this._ivTrackingSystem.usedIVs.size,\n collisionCount: this._ivTrackingSystem.collisionCount,\n entropyTests: this._ivTrackingSystem.entropyValidation.entropyTests,\n entropyFailures: this._ivTrackingSystem.entropyValidation.entropyFailures,\n rngTests: this._ivTrackingSystem.rngValidation.testsPerformed,\n weakRngDetected: this._ivTrackingSystem.rngValidation.weakRngDetected,\n emergencyMode: this._ivTrackingSystem.emergencyMode,\n sessionCount: this._ivTrackingSystem.sessionIVs.size,\n lastCleanup: this._lastIVCleanupTime || 0\n };\n }\n \n /**\n * Reset IV tracking system (for testing or emergency recovery)\n */\n _resetIVTrackingSystem() {\n this._secureLog('warn', '\uD83D\uDD04 Resetting IV tracking system');\n \n this._ivTrackingSystem.usedIVs.clear();\n this._ivTrackingSystem.ivHistory.clear();\n this._ivTrackingSystem.sessionIVs.clear();\n this._ivTrackingSystem.collisionCount = 0;\n this._ivTrackingSystem.entropyValidation.entropyTests = 0;\n this._ivTrackingSystem.entropyValidation.entropyFailures = 0;\n this._ivTrackingSystem.rngValidation.testsPerformed = 0;\n this._ivTrackingSystem.rngValidation.weakRngDetected = false;\n this._ivTrackingSystem.emergencyMode = false;\n \n this._secureLog('info', '\u2705 IV tracking system reset completed');\n }\n \n /**\n * Validate RNG quality\n */\n _validateRNGQuality() {\n const now = Date.now();\n \n // Validate RNG every 1000 IV generations\n if (this._ivTrackingSystem.rngValidation.testsPerformed % 1000 === 0) {\n try {\n // Generate test IVs and validate\n const testIVs = [];\n for (let i = 0; i < 100; i++) {\n testIVs.push(crypto.getRandomValues(new Uint8Array(12)));\n }\n \n // Check for duplicates in test set\n const testIVStrings = testIVs.map(iv => Array.from(iv).map(b => b.toString(16).padStart(2, '0')).join(''));\n const uniqueTestIVs = new Set(testIVStrings);\n \n if (uniqueTestIVs.size < 95) { // Allow some tolerance\n this._ivTrackingSystem.rngValidation.weakRngDetected = true;\n this._secureLog('error', '\uD83D\uDEA8 CRITICAL: Weak RNG detected in validation test', {\n uniqueIVs: uniqueTestIVs.size,\n totalTests: testIVs.length\n });\n }\n \n this._ivTrackingSystem.rngValidation.lastValidation = now;\n \n } catch (error) {\n this._secureLog('error', '\u274C RNG validation failed', {\n errorType: error.constructor.name\n });\n }\n }\n \n this._ivTrackingSystem.rngValidation.testsPerformed++;\n }\n \n /**\n * Handle mutex timeout with enhanced state validation\n */\n _handleMutexTimeout(mutexName, operationId, timeout) {\n const mutex = this[`_${mutexName}Mutex`];\n \n if (!mutex) {\n this._secureLog('error', `\u274C Mutex '${mutexName}' not found during timeout handling`);\n return;\n }\n \n // Validate timeout conditions\n if (mutex.lockId !== operationId) {\n this._secureLog('warn', `\u26A0\uFE0F Timeout for different operation ID on mutex '${mutexName}'`, {\n expectedOperationId: operationId,\n actualLockId: mutex.lockId,\n locked: mutex.locked\n });\n return;\n }\n \n if (!mutex.locked) {\n this._secureLog('warn', `\u26A0\uFE0F Timeout for already unlocked mutex '${mutexName}'`, {\n operationId: operationId\n });\n return;\n }\n \n try {\n // Calculate lock duration for monitoring\n const lockDuration = mutex.lockTime ? Date.now() - mutex.lockTime : 0;\n \n this._secureLog('warn', `\u26A0\uFE0F Mutex '${mutexName}' auto-released due to timeout`, {\n operationId: operationId,\n lockDuration: lockDuration,\n timeout: timeout,\n queueLength: mutex.queue.length\n });\n \n // Atomic release with state validation\n mutex.locked = false;\n mutex.lockId = null;\n mutex.lockTimeout = null;\n mutex.lockTime = null;\n \n // Process next in queue with error handling\n setTimeout(() => {\n try {\n this._processNextInQueue(mutexName);\n } catch (queueError) {\n this._secureLog('error', `\u274C Error processing queue after timeout for mutex '${mutexName}'`, {\n errorType: queueError.constructor.name,\n errorMessage: queueError.message\n });\n }\n }, 10);\n \n } catch (error) {\n this._secureLog('error', `\u274C Critical error during mutex timeout handling for '${mutexName}'`, {\n operationId: operationId,\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n \n // Force emergency unlock if timeout handling fails\n try {\n this._emergencyUnlockAllMutexes('timeoutHandler');\n } catch (emergencyError) {\n this._secureLog('error', `\u274C Emergency unlock failed during timeout handling`, {\n originalError: error.message,\n emergencyError: emergencyError.message\n });\n }\n }\n }\n\n /**\n * Validate mutex system after emergency unlock\n */\n _validateMutexSystemAfterEmergencyUnlock() {\n const mutexes = ['keyOperation', 'cryptoOperation', 'connectionOperation'];\n let validationErrors = 0;\n \n this._secureLog('info', '\uD83D\uDD0D Validating mutex system after emergency unlock');\n \n mutexes.forEach(mutexName => {\n const mutex = this[`_${mutexName}Mutex`];\n \n if (!mutex) {\n validationErrors++;\n this._secureLog('error', `\u274C Mutex '${mutexName}' not found after emergency unlock`);\n return;\n }\n \n // Validate mutex state consistency\n if (mutex.locked) {\n validationErrors++;\n this._secureLog('error', `\u274C Mutex '${mutexName}' still locked after emergency unlock`, {\n lockId: mutex.lockId,\n lockTime: mutex.lockTime\n });\n }\n \n if (mutex.lockId !== null) {\n validationErrors++;\n this._secureLog('error', `\u274C Mutex '${mutexName}' still has lock ID after emergency unlock`, {\n lockId: mutex.lockId\n });\n }\n \n if (mutex.lockTimeout !== null) {\n validationErrors++;\n this._secureLog('error', `\u274C Mutex '${mutexName}' still has timeout after emergency unlock`);\n }\n \n if (mutex.queue.length > 0) {\n validationErrors++;\n this._secureLog('error', `\u274C Mutex '${mutexName}' still has queue items after emergency unlock`, {\n queueLength: mutex.queue.length\n });\n }\n });\n \n // Validate key system state\n if (this._keySystemState) {\n if (this._keySystemState.isInitializing || \n this._keySystemState.isRotating || \n this._keySystemState.isDestroying) {\n validationErrors++;\n this._secureLog('error', `\u274C Key system state not properly reset after emergency unlock`, {\n isInitializing: this._keySystemState.isInitializing,\n isRotating: this._keySystemState.isRotating,\n isDestroying: this._keySystemState.isDestroying\n });\n }\n }\n \n if (validationErrors === 0) {\n this._secureLog('info', '\u2705 Mutex system validation passed after emergency unlock');\n } else {\n this._secureLog('error', `\u274C Mutex system validation failed after emergency unlock`, {\n validationErrors: validationErrors\n });\n \n // Force re-initialization if validation fails\n setTimeout(() => {\n this._emergencyRecoverMutexSystem();\n }, 1000);\n }\n }\n /**\n * NEW: Diagnostics of the mutex system state\n */\n _getMutexSystemDiagnostics() {\n const diagnostics = {\n timestamp: Date.now(),\n systemValid: this._validateMutexSystem(),\n mutexes: {},\n counters: { ...this._operationCounters },\n keySystemState: { ...this._keySystemState }\n };\n \n const mutexNames = ['keyOperation', 'cryptoOperation', 'connectionOperation'];\n \n mutexNames.forEach(mutexName => {\n const mutexPropertyName = `_${mutexName}Mutex`;\n const mutex = this[mutexPropertyName];\n \n if (mutex) {\n diagnostics.mutexes[mutexName] = {\n locked: mutex.locked,\n lockId: mutex.lockId,\n queueLength: mutex.queue.length,\n hasTimeout: !!mutex.lockTimeout\n };\n } else {\n diagnostics.mutexes[mutexName] = { error: 'not_found' };\n }\n });\n \n return diagnostics;\n }\n\n /**\n * FULLY FIXED createSecureOffer()\n * With race-condition protection and improved security\n */\n async createSecureOffer() {\n console.log('\uD83C\uDFAF createSecureOffer called');\n return this._withMutex('connectionOperation', async (operationId) => {\n this._secureLog('info', '\uD83D\uDCE4 Creating secure offer with mutex', {\n operationId: operationId,\n connectionAttempts: this.connectionAttempts,\n currentState: this.peerConnection?.connectionState || 'none'\n });\n \n try {\n // ============================================\n // PHASE 1: INITIALIZATION AND VALIDATION\n // ============================================\n console.log('\uD83C\uDFAF PHASE 1: Initialization and validation');\n \n // Reset notification flags for a new connection\n this._resetNotificationFlags();\n \n // Rate limiting check\n if (!this._checkRateLimit()) {\n throw new Error('Connection rate limit exceeded. Please wait before trying again.');\n }\n \n // Reset attempt counters\n this.connectionAttempts = 0;\n \n // Generate session salt (64 bytes for v4.0)\n this.sessionSalt = window.EnhancedSecureCryptoUtils.generateSalt();\n console.log('\uD83C\uDFAF PHASE 1 completed: Session salt generated');\n \n this._secureLog('debug', '\uD83E\uDDC2 Session salt generated', {\n operationId: operationId,\n saltLength: this.sessionSalt.length,\n isValidSalt: Array.isArray(this.sessionSalt) && this.sessionSalt.length === 64\n });\n \n // ============================================\n // PHASE 2: SECURE KEY GENERATION\n // ============================================\n console.log('\uD83C\uDFAF PHASE 2: Secure key generation');\n \n // Secure key generation via mutex\n const keyPairs = await this._generateEncryptionKeys();\n this.ecdhKeyPair = keyPairs.ecdhKeyPair;\n this.ecdsaKeyPair = keyPairs.ecdsaKeyPair;\n \n // Validate generated keys\n if (!this.ecdhKeyPair?.privateKey || !this.ecdhKeyPair?.publicKey) {\n throw new Error('Failed to generate valid ECDH key pair');\n }\n \n if (!this.ecdsaKeyPair?.privateKey || !this.ecdsaKeyPair?.publicKey) {\n throw new Error('Failed to generate valid ECDSA key pair');\n }\n \n // ============================================\n // PHASE 3: MITM PROTECTION AND FINGERPRINTING\n // ============================================\n console.log('\uD83C\uDFAF PHASE 3: MITM protection and fingerprinting');\n \n // MITM Protection: Compute unique key fingerprints\n const ecdhFingerprint = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(\n await crypto.subtle.exportKey('spki', this.ecdhKeyPair.publicKey)\n );\n const ecdsaFingerprint = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(\n await crypto.subtle.exportKey('spki', this.ecdsaKeyPair.publicKey)\n );\n \n // Validate fingerprints\n if (!ecdhFingerprint || !ecdsaFingerprint) {\n throw new Error('Failed to generate key fingerprints');\n }\n \n this._secureLog('info', 'Generated unique key pairs for MITM protection', {\n operationId: operationId,\n hasECDHFingerprint: !!ecdhFingerprint,\n hasECDSAFingerprint: !!ecdsaFingerprint,\n fingerprintLength: ecdhFingerprint.length,\n timestamp: Date.now()\n });\n \n // ============================================\n // PHASE 4: EXPORT SIGNED KEYS\n // ============================================\n console.log('\uD83C\uDFAF PHASE 4: Export signed keys');\n \n // Export keys with digital signatures\n const ecdhPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(\n this.ecdhKeyPair.publicKey,\n this.ecdsaKeyPair.privateKey,\n 'ECDH'\n );\n \n const ecdsaPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(\n this.ecdsaKeyPair.publicKey,\n this.ecdsaKeyPair.privateKey,\n 'ECDSA'\n );\n \n // CRITICAL: Strict validation of exported data with hard disconnect on failure\n // - Any validation failure in critical security path must abort connection\n // - No fallback allowed for cryptographic validation\n // - Prevent bypass of security checks through syntax/validation errors\n \n if (!ecdhPublicKeyData || typeof ecdhPublicKeyData !== 'object') {\n this._secureLog('error', 'CRITICAL: ECDH key export failed - invalid object structure', { operationId });\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key export validation failed - hard abort required');\n }\n \n if (!ecdhPublicKeyData.keyData || !ecdhPublicKeyData.signature) {\n this._secureLog('error', 'CRITICAL: ECDH key export incomplete - missing keyData or signature', { \n operationId,\n hasKeyData: !!ecdhPublicKeyData.keyData,\n hasSignature: !!ecdhPublicKeyData.signature \n });\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key export incomplete - hard abort required');\n }\n \n if (!ecdsaPublicKeyData || typeof ecdsaPublicKeyData !== 'object') {\n this._secureLog('error', 'CRITICAL: ECDSA key export failed - invalid object structure', { operationId });\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key export validation failed - hard abort required');\n }\n \n if (!ecdsaPublicKeyData.keyData || !ecdsaPublicKeyData.signature) {\n this._secureLog('error', 'CRITICAL: ECDSA key export incomplete - missing keyData or signature', { \n operationId,\n hasKeyData: !!ecdsaPublicKeyData.keyData,\n hasSignature: !!ecdsaPublicKeyData.signature \n });\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key export incomplete - hard abort required');\n }\n \n // ============================================\n // PHASE 5: UPDATE SECURITY FEATURES\n // ============================================\n console.log('\uD83C\uDFAF PHASE 5: Update security features');\n \n // Atomic update of security features\n this._updateSecurityFeatures({\n hasEncryption: true,\n hasECDH: true,\n hasECDSA: true,\n hasMutualAuth: true,\n hasMetadataProtection: true,\n hasEnhancedReplayProtection: true,\n hasNonExtractableKeys: true,\n hasRateLimiting: true,\n hasEnhancedValidation: true,\n hasPFS: true\n });\n \n // ============================================\n // PHASE 6: INITIALIZE PEER CONNECTION\n // ============================================\n console.log('\uD83C\uDFAF PHASE 6: Initialize peer connection');\n \n this.isInitiator = true;\n this.onStatusChange('connecting');\n \n // Create peer connection\n this.createPeerConnection();\n \n // Create main data channel\n this.dataChannel = this.peerConnection.createDataChannel('securechat', {\n ordered: true\n });\n \n // Setup data channel\n this.setupDataChannel(this.dataChannel);\n \n this._secureLog('debug', '\uD83D\uDD17 Data channel created', {\n operationId: operationId,\n channelLabel: this.dataChannel.label,\n channelOrdered: this.dataChannel.ordered\n });\n \n // ============================================\n // PHASE 7: CREATE SDP OFFER\n // ============================================\n console.log('\uD83C\uDFAF PHASE 7: Create SDP offer');\n \n // Create WebRTC offer\n console.log('\uD83C\uDFAF Creating WebRTC offer...');\n const offer = await this.peerConnection.createOffer({\n offerToReceiveAudio: false,\n offerToReceiveVideo: false\n });\n console.log('\uD83C\uDFAF WebRTC offer created successfully');\n \n // Set local description\n console.log('\uD83C\uDFAF Setting local description...');\n await this.peerConnection.setLocalDescription(offer);\n console.log('\uD83C\uDFAF Local description set successfully');\n \n // Extract and store our DTLS fingerprint for out-of-band verification\n console.log('\uD83C\uDFAF Extracting DTLS fingerprint...');\n try {\n const ourFingerprint = this._extractDTLSFingerprintFromSDP(offer.sdp);\n this.expectedDTLSFingerprint = ourFingerprint;\n console.log('\uD83C\uDFAF DTLS fingerprint extracted successfully');\n \n this._secureLog('info', 'Generated DTLS fingerprint for out-of-band verification', {\n fingerprint: ourFingerprint,\n context: 'offer_creation'\n });\n \n // Notify UI that fingerprint is ready for out-of-band verification\n this.deliverMessageToUI(`\uD83D\uDD10 DTLS fingerprint ready for verification: ${ourFingerprint}`, 'system');\n } catch (error) {\n this._secureLog('error', 'Failed to extract DTLS fingerprint from offer', { error: error.message });\n // Continue without fingerprint validation (fallback mode)\n }\n \n // Await ICE gathering\n await this.waitForIceGathering();\n \n this._secureLog('debug', '\uD83E\uDDCA ICE gathering completed', {\n operationId: operationId,\n iceGatheringState: this.peerConnection.iceGatheringState,\n connectionState: this.peerConnection.connectionState\n });\n \n // ============================================\n // PHASE 8: GENERATE SAS FOR OUT-OF-BAND VERIFICATION\n // ============================================\n console.log('\uD83C\uDFAF PHASE 8: Generate SAS for out-of-band verification');\n\n this.verificationCode = window.EnhancedSecureCryptoUtils.generateVerificationCode();\n console.log('\uD83C\uDFAF Placeholder verification code generated:', this.verificationCode);\n \n // Validate verification code\n if (!this.verificationCode || this.verificationCode.length < EnhancedSecureWebRTCManager.SIZES.VERIFICATION_CODE_MIN_LENGTH) {\n throw new Error('Failed to generate valid verification code');\n }\n \n // ============================================\n // PHASE 9: MUTUAL AUTHENTICATION CHALLENGE\n // ============================================\n console.log('\uD83C\uDFAF PHASE 9: Mutual authentication challenge');\n \n // Generate challenge for mutual authentication\n const authChallenge = window.EnhancedSecureCryptoUtils.generateMutualAuthChallenge();\n \n if (!authChallenge) {\n throw new Error('Failed to generate mutual authentication challenge');\n }\n \n // ============================================\n // PHASE 10: SESSION ID FOR MITM PROTECTION\n // ============================================\n console.log('\uD83C\uDFAF PHASE 10: Session ID for MITM protection');\n \n // MITM Protection: Generate session-specific ID\n this.sessionId = Array.from(crypto.getRandomValues(new Uint8Array(EnhancedSecureWebRTCManager.SIZES.SESSION_ID_LENGTH)))\n .map(b => b.toString(16).padStart(2, '0')).join('');\n \n // Validate session ID\n if (!this.sessionId || this.sessionId.length !== (EnhancedSecureWebRTCManager.SIZES.SESSION_ID_LENGTH * 2)) {\n throw new Error('Failed to generate valid session ID');\n }\n \n // Generate connection ID for AAD\n this.connectionId = Array.from(crypto.getRandomValues(new Uint8Array(8)))\n .map(b => b.toString(16).padStart(2, '0')).join('');\n \n // ============================================\n // PHASE 11: SECURITY LEVEL CALCULATION\n // ============================================\n console.log('\uD83C\uDFAF PHASE 11: Security level calculation');\n \n // Preliminary security level calculation\n let securityLevel;\n try {\n securityLevel = await this.calculateSecurityLevel();\n } catch (error) {\n this._secureLog('warn', '\u26A0\uFE0F Security level calculation failed, using fallback', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n \n // Fallback value\n securityLevel = {\n level: 'enhanced',\n score: 75,\n passedChecks: 10,\n totalChecks: 15,\n isRealData: false\n };\n }\n \n // ============================================\n // PHASE 12: CREATE OFFER PACKAGE\n // ============================================\n console.log('\uD83C\uDFAF PHASE 12: Create offer package');\n \n const currentTimestamp = Date.now();\n console.log('\uD83C\uDFAF Creating offer package object...');\n \n const offerPackage = {\n // Core information\n type: 'enhanced_secure_offer',\n sdp: this.peerConnection.localDescription.sdp,\n version: '4.0',\n timestamp: currentTimestamp,\n \n // Cryptographic keys\n ecdhPublicKey: ecdhPublicKeyData,\n ecdsaPublicKey: ecdsaPublicKeyData,\n \n // Session data\n salt: this.sessionSalt,\n sessionId: this.sessionId,\n connectionId: this.connectionId,\n \n // Authentication\n verificationCode: this.verificationCode,\n authChallenge: authChallenge,\n \n // Security metadata\n securityLevel: securityLevel,\n \n // Additional fields for validation\n keyFingerprints: {\n ecdh: ecdhFingerprint.substring(0, 16), // First 16 chars for validation\n ecdsa: ecdsaFingerprint.substring(0, 16)\n },\n \n // Optional capabilities info\n capabilities: {\n supportsFileTransfer: true,\n supportsEnhancedSecurity: true,\n supportsKeyRotation: true,\n supportsFakeTraffic: this.fakeTrafficConfig.enabled,\n supportsDecoyChannels: this.decoyChannelConfig.enabled\n }\n };\n console.log('\uD83C\uDFAF Offer package object created successfully');\n \n // ============================================\n // PHASE 13: VALIDATE OFFER PACKAGE\n // ============================================\n console.log('\uD83C\uDFAF PHASE 13: Validate offer package');\n \n // Final validation of the generated package\n console.log('\uD83C\uDFAF Validating offer package...');\n try {\n const validationResult = this.validateEnhancedOfferData(offerPackage);\n console.log('\uD83C\uDFAF Validation result:', validationResult);\n if (!validationResult) {\n console.log('\uD83C\uDFAF Offer package validation FAILED');\n throw new Error('Generated offer package failed validation');\n }\n console.log('\uD83C\uDFAF Offer package validation PASSED');\n } catch (validationError) {\n console.log('\uD83C\uDFAF Validation ERROR:', validationError.message);\n throw new Error(`Offer package validation error: ${validationError.message}`);\n }\n \n // ============================================\n // PHASE 14: LOGGING AND EVENTS\n // ============================================\n console.log('\uD83C\uDFAF PHASE 14: Logging and events');\n \n this._secureLog('info', 'Enhanced secure offer created successfully', {\n operationId: operationId,\n version: offerPackage.version,\n hasECDSA: true,\n hasMutualAuth: true,\n hasSessionId: !!offerPackage.sessionId,\n securityLevel: securityLevel.level,\n timestamp: currentTimestamp,\n capabilitiesCount: Object.keys(offerPackage.capabilities).length\n });\n \n // Dispatch event about new connection\n document.dispatchEvent(new CustomEvent('new-connection', {\n detail: { \n type: 'offer',\n timestamp: currentTimestamp,\n securityLevel: securityLevel.level,\n operationId: operationId\n }\n }));\n \n // ============================================\n // PHASE 15: RETURN RESULT\n // ============================================\n console.log('\uD83C\uDFAF PHASE 15: Return result');\n \n console.log('\uD83C\uDFAF createSecureOffer completed successfully, returning offerPackage');\n return offerPackage;\n \n } catch (error) {\n // ============================================\n // ERROR HANDLING\n // ============================================\n \n this._secureLog('error', '\u274C Enhanced secure offer creation failed in critical section', {\n operationId: operationId,\n errorType: error.constructor.name,\n errorMessage: error.message,\n phase: this._determineErrorPhase(error),\n connectionAttempts: this.connectionAttempts\n });\n \n // Cleanup state on error\n this._cleanupFailedOfferCreation();\n \n // Update status\n this.onStatusChange('disconnected');\n \n // Re-throw for upper-level handling\n throw error;\n }\n }, 15000); // 15 seconds timeout for the entire offer creation\n }\n\n /**\n * HELPER: Determine the phase where the error occurred\n */\n _determineErrorPhase(error) {\n const message = error.message.toLowerCase();\n \n if (message.includes('rate limit')) return 'rate_limiting';\n if (message.includes('key pair') || message.includes('generate')) return 'key_generation';\n if (message.includes('fingerprint')) return 'fingerprinting';\n if (message.includes('export') || message.includes('signature')) return 'key_export';\n if (message.includes('peer connection')) return 'webrtc_setup';\n if (message.includes('offer') || message.includes('sdp')) return 'sdp_creation';\n if (message.includes('verification')) return 'verification_setup';\n if (message.includes('session')) return 'session_setup';\n if (message.includes('validation')) return 'package_validation';\n \n return 'unknown';\n }\n\n /**\n * Secure cleanup state after failed offer creation\n */\n _cleanupFailedOfferCreation() {\n try {\n // Secure wipe of cryptographic materials\n this._secureCleanupCryptographicMaterials();\n \n // Close peer connection if it was created\n if (this.peerConnection) {\n this.peerConnection.close();\n this.peerConnection = null;\n }\n \n // Clear data channel\n if (this.dataChannel) {\n this.dataChannel.close();\n this.dataChannel = null;\n }\n \n // Reset flags\n this.isInitiator = false;\n this.isVerified = false;\n \n // Reset security features to baseline\n this._updateSecurityFeatures({\n hasEncryption: false,\n hasECDH: false,\n hasECDSA: false,\n hasMutualAuth: false,\n hasMetadataProtection: false,\n hasEnhancedReplayProtection: false,\n hasNonExtractableKeys: false,\n hasEnhancedValidation: false,\n hasPFS: false\n });\n \n // Force garbage collection\n this._forceGarbageCollection();\n \n this._secureLog('debug', '\uD83D\uDD12 Failed offer creation cleanup completed with secure memory wipe');\n \n } catch (cleanupError) {\n this._secureLog('error', '\u274C Error during offer creation cleanup', {\n errorType: cleanupError.constructor.name,\n errorMessage: cleanupError.message\n });\n }\n }\n\n /**\n * HELPER: Atomic update of security features (if not added yet)\n */\n _updateSecurityFeatures(updates) {\n const oldFeatures = { ...this.securityFeatures };\n \n try {\n Object.assign(this.securityFeatures, updates);\n \n this._secureLog('debug', '\uD83D\uDD27 Security features updated', {\n updatedCount: Object.keys(updates).length,\n totalFeatures: Object.keys(this.securityFeatures).length\n });\n \n } catch (error) {\n // Roll back on error\n this.securityFeatures = oldFeatures;\n this._secureLog('error', '\u274C Security features update failed, rolled back', {\n errorType: error.constructor.name\n });\n throw error;\n }\n }\n\n /**\n * FULLY FIXED METHOD createSecureAnswer()\n * With race-condition protection and enhanced security\n */\n async createSecureAnswer(offerData) {\n console.log('\uD83C\uDFAF createSecureAnswer called with offerData:', offerData ? 'present' : 'null');\n return this._withMutex('connectionOperation', async (operationId) => {\n this._secureLog('info', '\uD83D\uDCE8 Creating secure answer with mutex', {\n operationId: operationId,\n hasOfferData: !!offerData,\n offerType: offerData?.type,\n offerVersion: offerData?.version,\n offerTimestamp: offerData?.timestamp\n });\n \n try {\n // ============================================\n // PHASE 1: PRE-VALIDATION OF OFFER\n // ============================================\n \n // Reset notification flags for a new connection\n this._resetNotificationFlags();\n \n this._secureLog('debug', 'Starting enhanced offer validation', {\n operationId: operationId,\n hasOfferData: !!offerData,\n offerType: offerData?.type,\n hasECDHKey: !!offerData?.ecdhPublicKey,\n hasECDSAKey: !!offerData?.ecdsaPublicKey,\n hasSalt: !!offerData?.salt\n });\n \n // Strict input validation\n if (!this.validateEnhancedOfferData(offerData)) {\n throw new Error('Invalid connection data format - failed enhanced validation');\n }\n \n // Rate limiting check\n if (!window.EnhancedSecureCryptoUtils.rateLimiter.checkConnectionRate(this.rateLimiterId)) {\n throw new Error('Connection rate limit exceeded. Please wait before trying again.');\n }\n \n // ============================================\n // PHASE 2: SECURITY AND ANTI-REPLAY PROTECTION\n // ============================================\n \n // MITM Protection: Validate offer data structure\n if (!offerData.timestamp || !offerData.version) {\n throw new Error('Missing required security fields in offer data \u2013 possible MITM attack');\n }\n \n // Replay attack protection (window reduced to 5 minutes)\n const offerAge = Date.now() - offerData.timestamp;\n const MAX_OFFER_AGE = 300000; // 5 minutes instead of 1 hour\n \n if (offerAge > MAX_OFFER_AGE) {\n this._secureLog('error', 'Offer data is too old - possible replay attack', {\n operationId: operationId,\n offerAge: Math.round(offerAge / 1000),\n maxAllowedAge: Math.round(MAX_OFFER_AGE / 1000),\n timestamp: offerData.timestamp\n });\n \n // Notify the main code about the replay attack\n if (this.onAnswerError) {\n this.onAnswerError('replay_attack', 'Offer data is too old \u2013 possible replay attack');\n }\n \n throw new Error('Offer data is too old \u2013 possible replay attack');\n }\n \n // Protocol version compatibility check\n if (offerData.version !== '4.0') {\n this._secureLog('warn', 'Protocol version mismatch detected', {\n operationId: operationId,\n expectedVersion: '4.0',\n receivedVersion: offerData.version\n });\n \n // For backward compatibility with v3.0, a fallback can be added\n if (offerData.version !== '3.0') {\n throw new Error(`Unsupported protocol version: ${offerData.version}`);\n }\n }\n \n // ============================================\n // PHASE 3: EXTRACT AND VALIDATE SESSION SALT\n // ============================================\n \n // Set session salt from offer\n this.sessionSalt = offerData.salt;\n \n // Validate session salt\n if (!Array.isArray(this.sessionSalt)) {\n throw new Error('Invalid session salt format - must be array');\n }\n \n const expectedSaltLength = offerData.version === '4.0' ? 64 : 32;\n if (this.sessionSalt.length !== expectedSaltLength) {\n throw new Error(`Invalid session salt length: expected ${expectedSaltLength}, got ${this.sessionSalt.length}`);\n }\n \n // MITM Protection: Check salt integrity\n const saltFingerprint = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(this.sessionSalt);\n \n this._secureLog('info', 'Session salt validated successfully', {\n operationId: operationId,\n saltLength: this.sessionSalt.length,\n saltFingerprint: saltFingerprint.substring(0, 8)\n });\n \n // ============================================\n // PHASE 4: SECURE GENERATION OF OUR KEYS\n // ============================================\n \n // Secure generation of our keys via mutex\n const keyPairs = await this._generateEncryptionKeys();\n this.ecdhKeyPair = keyPairs.ecdhKeyPair;\n this.ecdsaKeyPair = keyPairs.ecdsaKeyPair;\n \n // Additional validation of generated keys\n if (!(this.ecdhKeyPair?.privateKey instanceof CryptoKey)) {\n this._secureLog('error', 'Local ECDH private key is not a CryptoKey', {\n operationId: operationId,\n hasKeyPair: !!this.ecdhKeyPair,\n privateKeyType: typeof this.ecdhKeyPair?.privateKey,\n privateKeyAlgorithm: this.ecdhKeyPair?.privateKey?.algorithm?.name\n });\n throw new Error('Local ECDH private key is not a valid CryptoKey');\n }\n \n // ============================================\n // PHASE 5: IMPORT AND VERIFY PEER KEYS\n // ============================================\n \n // Import peer ECDSA public key for signature verification\n let peerECDSAPublicKey;\n \n try {\n peerECDSAPublicKey = await crypto.subtle.importKey(\n 'spki',\n new Uint8Array(offerData.ecdsaPublicKey.keyData),\n {\n name: 'ECDSA',\n namedCurve: 'P-384'\n },\n false,\n ['verify']\n );\n } catch (error) {\n this._throwSecureError(error, 'ecdsa_key_import');\n }\n \n // ============================================\n // PHASE 6: IMPORT AND VERIFY ECDH KEY\n // ============================================\n \n // Import and verify ECDH public key using verified ECDSA key\n let peerECDHPublicKey;\n \n try {\n peerECDHPublicKey = await window.EnhancedSecureCryptoUtils.importSignedPublicKey(\n offerData.ecdhPublicKey,\n peerECDSAPublicKey,\n 'ECDH'\n );\n } catch (error) {\n this._secureLog('error', 'Failed to import signed ECDH public key', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n this._throwSecureError(error, 'ecdh_key_import');\n }\n \n // Final validation of ECDH key\n if (!(peerECDHPublicKey instanceof CryptoKey)) {\n this._secureLog('error', 'Peer ECDH public key is not a CryptoKey', {\n operationId: operationId,\n publicKeyType: typeof peerECDHPublicKey,\n publicKeyAlgorithm: peerECDHPublicKey?.algorithm?.name\n });\n throw new Error('Peer ECDH public key is not a valid CryptoKey');\n }\n \n // Save peer key for PFS rotation\n this.peerPublicKey = peerECDHPublicKey;\n \n // ============================================\n // PHASE 7: DERIVE SHARED ENCRYPTION KEYS\n // ============================================\n \n // Derive shared keys with metadata protection\n let derivedKeys;\n \n try {\n derivedKeys = await window.EnhancedSecureCryptoUtils.deriveSharedKeys(\n this.ecdhKeyPair.privateKey,\n peerECDHPublicKey,\n this.sessionSalt\n );\n } catch (error) {\n this._secureLog('error', 'Failed to derive shared keys', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n this._throwSecureError(error, 'key_derivation');\n }\n \n // Securely set keys via helper\n await this._setEncryptionKeys(\n derivedKeys.encryptionKey,\n derivedKeys.macKey,\n derivedKeys.metadataKey,\n derivedKeys.fingerprint\n );\n \n // Additional validation of installed keys\n if (!(this.encryptionKey instanceof CryptoKey) || \n !(this.macKey instanceof CryptoKey) || \n !(this.metadataKey instanceof CryptoKey)) {\n \n this._secureLog('error', 'Invalid key types after derivation', {\n operationId: operationId,\n encryptionKeyType: typeof this.encryptionKey,\n macKeyType: typeof this.macKey,\n metadataKeyType: typeof this.metadataKey\n });\n throw new Error('Invalid key types after derivation');\n }\n \n // Set verification code from offer\n this.verificationCode = offerData.verificationCode;\n \n this._secureLog('info', 'Encryption keys derived and set successfully', {\n operationId: operationId,\n hasEncryptionKey: !!this.encryptionKey,\n hasMacKey: !!this.macKey,\n hasMetadataKey: !!this.metadataKey,\n hasKeyFingerprint: !!this.keyFingerprint,\n mitmProtection: 'enabled',\n signatureVerified: true\n });\n \n // ============================================\n // PHASE 8: UPDATE SECURITY FEATURES\n // ============================================\n \n // Atomic update of security features\n this._updateSecurityFeatures({\n hasEncryption: true,\n hasECDH: true,\n hasECDSA: true,\n hasMutualAuth: true,\n hasMetadataProtection: true,\n hasEnhancedReplayProtection: true,\n hasNonExtractableKeys: true,\n hasRateLimiting: true,\n hasEnhancedValidation: true,\n hasPFS: true\n });\n \n // PFS: Initialize key version tracking\n this.currentKeyVersion = 0;\n this.lastKeyRotation = Date.now();\n this.keyVersions.set(0, {\n salt: this.sessionSalt,\n timestamp: this.lastKeyRotation,\n messageCount: 0\n });\n \n // ============================================\n // PHASE 9: CREATE AUTHENTICATION PROOF\n // ============================================\n \n // Create proof for mutual authentication\n let authProof;\n \n if (offerData.authChallenge) {\n try {\n authProof = await window.EnhancedSecureCryptoUtils.createAuthProof(\n offerData.authChallenge,\n this.ecdsaKeyPair.privateKey,\n this.ecdsaKeyPair.publicKey\n );\n } catch (error) {\n this._secureLog('error', 'Failed to create authentication proof', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n this._throwSecureError(error, 'authentication_proof_creation');\n }\n } else {\n this._secureLog('warn', 'No auth challenge in offer - mutual auth disabled', {\n operationId: operationId\n });\n }\n \n // ============================================\n // PHASE 10: INITIALIZE WEBRTC\n // ============================================\n \n this.isInitiator = false;\n this.onStatusChange('connecting');\n \n // DEBUG: Check keyFingerprint before calling onKeyExchange\n console.log('Before onKeyExchange - keyFingerprint:', this.keyFingerprint);\n this.onKeyExchange(this.keyFingerprint);\n \n // Create peer connection first\n this.createPeerConnection();\n \n // Validate DTLS fingerprint before setting remote description\n if (this.strictDTLSValidation) {\n try {\n const receivedFingerprint = this._extractDTLSFingerprintFromSDP(offerData.sdp);\n \n if (this.expectedDTLSFingerprint) {\n this._validateDTLSFingerprint(receivedFingerprint, this.expectedDTLSFingerprint, 'offer_validation');\n } else {\n // Store fingerprint for future validation (first connection)\n this.expectedDTLSFingerprint = receivedFingerprint;\n this._secureLog('info', 'Stored DTLS fingerprint for future validation', {\n fingerprint: receivedFingerprint,\n context: 'first_connection'\n });\n }\n } catch (error) {\n this._secureLog('warn', 'DTLS fingerprint validation failed - continuing in fallback mode', { \n error: error.message,\n context: 'offer_validation'\n });\n // Continue without strict fingerprint validation for first connection\n // This allows the connection to proceed while maintaining security awareness\n }\n } else {\n this._secureLog('info', 'DTLS fingerprint validation disabled - proceeding without validation');\n }\n\n // Set remote description from offer\n try {\n this._secureLog('debug', 'Setting remote description from offer', {\n operationId: operationId,\n sdpLength: offerData.sdp?.length || 0\n });\n \n await this.peerConnection.setRemoteDescription(new RTCSessionDescription({\n type: 'offer',\n sdp: offerData.sdp\n }));\n \n this._secureLog('debug', 'Remote description set successfully', {\n operationId: operationId,\n signalingState: this.peerConnection.signalingState\n });\n } catch (error) {\n this._secureLog('error', 'Failed to set remote description', { \n error: error.message,\n operationId: operationId\n });\n this._throwSecureError(error, 'webrtc_remote_description');\n }\n \n this._secureLog('debug', '\uD83D\uDD17 Remote description set successfully', {\n operationId: operationId,\n connectionState: this.peerConnection.connectionState,\n signalingState: this.peerConnection.signalingState\n });\n \n // ============================================\n // PHASE 11: CREATE SDP ANSWER\n // ============================================\n \n // Create WebRTC answer\n let answer;\n \n try {\n answer = await this.peerConnection.createAnswer({\n offerToReceiveAudio: false,\n offerToReceiveVideo: false\n });\n } catch (error) {\n this._throwSecureError(error, 'webrtc_create_answer');\n }\n \n // Set local description\n try {\n await this.peerConnection.setLocalDescription(answer);\n } catch (error) {\n this._throwSecureError(error, 'webrtc_local_description');\n }\n \n // Extract and store our DTLS fingerprint for out-of-band verification\n try {\n const ourFingerprint = this._extractDTLSFingerprintFromSDP(answer.sdp);\n this.expectedDTLSFingerprint = ourFingerprint;\n \n this._secureLog('info', 'Generated DTLS fingerprint for out-of-band verification', {\n fingerprint: ourFingerprint,\n context: 'answer_creation'\n });\n \n // Notify UI that fingerprint is ready for out-of-band verification\n this.deliverMessageToUI(`\uD83D\uDD10 DTLS fingerprint ready for verification: ${ourFingerprint}`, 'system');\n } catch (error) {\n this._secureLog('error', 'Failed to extract DTLS fingerprint from answer', { error: error.message });\n // Continue without fingerprint validation (fallback mode)\n }\n \n \n // Await ICE gathering\n await this.waitForIceGathering();\n \n this._secureLog('debug', '\uD83E\uDDCA ICE gathering completed for answer', {\n operationId: operationId,\n iceGatheringState: this.peerConnection.iceGatheringState,\n connectionState: this.peerConnection.connectionState\n });\n \n // ============================================\n // PHASE 12: EXPORT OUR KEYS\n // ============================================\n \n // Export our keys with signatures\n const ecdhPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(\n this.ecdhKeyPair.publicKey,\n this.ecdsaKeyPair.privateKey,\n 'ECDH'\n );\n \n const ecdsaPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(\n this.ecdsaKeyPair.publicKey,\n this.ecdsaKeyPair.privateKey,\n 'ECDSA'\n );\n \n if (!ecdhPublicKeyData || typeof ecdhPublicKeyData !== 'object') {\n this._secureLog('error', 'CRITICAL: ECDH key export failed - invalid object structure', { operationId });\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key export validation failed - hard abort required');\n }\n \n if (!ecdhPublicKeyData.keyData || !ecdhPublicKeyData.signature) {\n this._secureLog('error', 'CRITICAL: ECDH key export incomplete - missing keyData or signature', { \n operationId,\n hasKeyData: !!ecdhPublicKeyData.keyData,\n hasSignature: !!ecdhPublicKeyData.signature \n });\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key export incomplete - hard abort required');\n }\n \n if (!ecdsaPublicKeyData || typeof ecdsaPublicKeyData !== 'object') {\n this._secureLog('error', 'CRITICAL: ECDSA key export failed - invalid object structure', { operationId });\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key export validation failed - hard abort required');\n }\n \n if (!ecdsaPublicKeyData.keyData || !ecdsaPublicKeyData.signature) {\n this._secureLog('error', 'CRITICAL: ECDSA key export incomplete - missing keyData or signature', { \n operationId,\n hasKeyData: !!ecdsaPublicKeyData.keyData,\n hasSignature: !!ecdsaPublicKeyData.signature \n });\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key export incomplete - hard abort required');\n }\n \n // ============================================\n // PHASE 13: SECURITY LEVEL CALCULATION\n // ============================================\n \n // Calculate security level\n let securityLevel;\n \n try {\n securityLevel = await this.calculateSecurityLevel();\n } catch (error) {\n this._secureLog('warn', '\u26A0\uFE0F Security level calculation failed, using fallback', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n \n // Fallback value\n securityLevel = {\n level: 'enhanced',\n score: 80,\n passedChecks: 12,\n totalChecks: 15,\n isRealData: false\n };\n }\n \n // ============================================\n // PHASE 14: CREATE ANSWER PACKAGE\n // ============================================\n \n const currentTimestamp = Date.now();\n \n const answerPackage = {\n // Core information\n type: 'enhanced_secure_answer',\n sdp: this.peerConnection.localDescription.sdp,\n version: '4.0',\n timestamp: currentTimestamp,\n \n // Cryptographic keys\n ecdhPublicKey: ecdhPublicKeyData,\n ecdsaPublicKey: ecdsaPublicKeyData,\n \n // Authentication\n authProof: authProof,\n \n // Security metadata\n securityLevel: securityLevel,\n \n // Additional security fields\n sessionConfirmation: {\n saltFingerprint: saltFingerprint.substring(0, 16),\n keyDerivationSuccess: true,\n mutualAuthEnabled: !!authProof\n },\n \n // Answerer capabilities\n capabilities: {\n supportsFileTransfer: true,\n supportsEnhancedSecurity: true,\n supportsKeyRotation: true,\n supportsFakeTraffic: this.fakeTrafficConfig.enabled,\n supportsDecoyChannels: this.decoyChannelConfig.enabled,\n protocolVersion: '4.0'\n }\n };\n \n // ============================================\n // PHASE 15: VALIDATION AND LOGGING\n // ============================================\n \n // Final validation of the answer package\n if (!answerPackage.sdp || !answerPackage.ecdhPublicKey || !answerPackage.ecdsaPublicKey) {\n throw new Error('Generated answer package is incomplete');\n }\n \n this._secureLog('info', 'Enhanced secure answer created successfully', {\n operationId: operationId,\n version: answerPackage.version,\n hasECDSA: true,\n hasMutualAuth: !!authProof,\n hasSessionConfirmation: !!answerPackage.sessionConfirmation,\n securityLevel: securityLevel.level,\n timestamp: currentTimestamp,\n processingTime: currentTimestamp - offerData.timestamp\n });\n \n // Dispatch event about new connection\n document.dispatchEvent(new CustomEvent('new-connection', {\n detail: { \n type: 'answer',\n timestamp: currentTimestamp,\n securityLevel: securityLevel.level,\n operationId: operationId\n }\n }));\n \n // ============================================\n // PHASE 16: SCHEDULE SECURITY CALCULATIONS\n // ============================================\n \n // Plan security calculation after connection\n setTimeout(async () => {\n try {\n const realSecurityData = await this.calculateAndReportSecurityLevel();\n if (realSecurityData) {\n this.notifySecurityUpdate();\n this._secureLog('info', '\u2705 Post-connection security level calculated', {\n operationId: operationId,\n level: realSecurityData.level\n });\n }\n } catch (error) {\n this._secureLog('error', '\u274C Error calculating post-connection security', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n }\n }, 1000);\n \n // Retry if the first calculation fails\n setTimeout(async () => {\n if (!this.lastSecurityCalculation || this.lastSecurityCalculation.score < 50) {\n this._secureLog('info', '\uD83D\uDD04 Retrying security calculation', {\n operationId: operationId\n });\n await this.calculateAndReportSecurityLevel();\n this.notifySecurityUpdate();\n }\n }, 3000);\n \n // Final security update\n this.notifySecurityUpdate();\n \n // ============================================\n // PHASE 17: RETURN RESULT\n // ============================================\n \n return answerPackage;\n \n } catch (error) {\n // ============================================\n // ERROR HANDLING\n // ============================================\n \n this._secureLog('error', '\u274C Enhanced secure answer creation failed in critical section', {\n operationId: operationId,\n errorType: error.constructor.name,\n errorMessage: error.message,\n phase: this._determineAnswerErrorPhase(error),\n offerAge: offerData?.timestamp ? Date.now() - offerData.timestamp : 'unknown'\n });\n \n // Cleanup state on error\n this._cleanupFailedAnswerCreation();\n \n // Update status\n this.onStatusChange('disconnected');\n \n // Special handling of security errors\n if (this.onAnswerError) {\n if (error.message.includes('too old') || error.message.includes('replay')) {\n this.onAnswerError('replay_attack', error.message);\n } else if (error.message.includes('MITM') || error.message.includes('signature')) {\n this.onAnswerError('security_violation', error.message);\n } else if (error.message.includes('validation') || error.message.includes('format')) {\n this.onAnswerError('invalid_format', error.message);\n } else {\n this.onAnswerError('general_error', error.message);\n }\n }\n \n // Re-throw for upper-level handling\n throw error;\n }\n }, 20000); // 20 seconds timeout for the entire answer creation (longer than offer)\n }\n\n /**\n * HELPER: Determine error phase for answer\n */\n _determineAnswerErrorPhase(error) {\n const message = error.message.toLowerCase();\n \n if (message.includes('validation') || message.includes('format')) return 'offer_validation';\n if (message.includes('rate limit')) return 'rate_limiting';\n if (message.includes('replay') || message.includes('too old')) return 'replay_protection';\n if (message.includes('salt')) return 'salt_validation';\n if (message.includes('key pair') || message.includes('generate')) return 'key_generation';\n if (message.includes('import') || message.includes('ecdsa') || message.includes('ecdh')) return 'key_import';\n if (message.includes('signature') || message.includes('mitm')) return 'signature_verification';\n if (message.includes('derive') || message.includes('shared')) return 'key_derivation';\n if (message.includes('auth') || message.includes('proof')) return 'authentication';\n if (message.includes('remote description') || message.includes('local description')) return 'webrtc_setup';\n if (message.includes('answer') || message.includes('sdp')) return 'sdp_creation';\n if (message.includes('export')) return 'key_export';\n if (message.includes('security level')) return 'security_calculation';\n \n return 'unknown';\n }\n\n /**\n * HELPER: Cleanup state after failed answer creation\n */\n /**\n * Secure cleanup state after failed answer creation\n */\n _cleanupFailedAnswerCreation() {\n try {\n // Secure wipe of cryptographic materials\n this._secureCleanupCryptographicMaterials();\n \n // Secure wipe of PFS key versions\n this.currentKeyVersion = 0;\n this.keyVersions.clear();\n this.oldKeys.clear();\n \n // Close peer connection if created\n if (this.peerConnection) {\n this.peerConnection.close();\n this.peerConnection = null;\n }\n \n // Clear data channel\n if (this.dataChannel) {\n this.dataChannel.close();\n this.dataChannel = null;\n }\n \n // Reset flags and counters\n this.isInitiator = false;\n this.isVerified = false;\n this.sequenceNumber = 0;\n this.expectedSequenceNumber = 0;\n this.messageCounter = 0;\n this.processedMessageIds.clear();\n this.replayWindow.clear(); // Clear replay window\n \n // Reset security features to baseline\n this._updateSecurityFeatures({\n hasEncryption: false,\n hasECDH: false,\n hasECDSA: false,\n hasMutualAuth: false,\n hasMetadataProtection: false,\n hasEnhancedReplayProtection: false,\n hasNonExtractableKeys: false,\n hasEnhancedValidation: false,\n hasPFS: false\n });\n \n // Force garbage collection\n this._forceGarbageCollection();\n \n this._secureLog('debug', '\uD83D\uDD12 Failed answer creation cleanup completed with secure memory wipe');\n \n } catch (cleanupError) {\n this._secureLog('error', '\u274C Error during answer creation cleanup', {\n errorType: cleanupError.constructor.name,\n errorMessage: cleanupError.message\n });\n }\n }\n\n /**\n * HELPER: Securely set encryption keys (if not set yet)\n */\n async _setEncryptionKeys(encryptionKey, macKey, metadataKey, keyFingerprint) {\n return this._withMutex('keyOperation', async (operationId) => {\n this._secureLog('info', '\uD83D\uDD10 Setting encryption keys with mutex', {\n operationId: operationId\n });\n \n // Validate all keys before setting\n if (!(encryptionKey instanceof CryptoKey) ||\n !(macKey instanceof CryptoKey) ||\n !(metadataKey instanceof CryptoKey)) {\n throw new Error('Invalid key types provided');\n }\n \n if (!keyFingerprint || typeof keyFingerprint !== 'string') {\n throw new Error('Invalid key fingerprint provided');\n }\n \n // Atomically set all keys\n const oldKeys = {\n encryptionKey: this.encryptionKey,\n macKey: this.macKey,\n metadataKey: this.metadataKey,\n keyFingerprint: this.keyFingerprint\n };\n \n try {\n this.encryptionKey = encryptionKey;\n this.macKey = macKey;\n this.metadataKey = metadataKey;\n this.keyFingerprint = keyFingerprint;\n \n // Reset counters\n this.sequenceNumber = 0;\n this.expectedSequenceNumber = 0;\n this.messageCounter = 0;\n this.processedMessageIds.clear();\n this.replayWindow.clear(); // Clear replay window\n \n this._secureLog('info', '\u2705 Encryption keys set successfully', {\n operationId: operationId,\n hasAllKeys: !!(this.encryptionKey && this.macKey && this.metadataKey),\n hasFingerprint: !!this.keyFingerprint\n });\n \n return true;\n \n } catch (error) {\n // Roll back on error\n this.encryptionKey = oldKeys.encryptionKey;\n this.macKey = oldKeys.macKey;\n this.metadataKey = oldKeys.metadataKey;\n this.keyFingerprint = oldKeys.keyFingerprint;\n \n this._secureLog('error', '\u274C Key setting failed, rolled back', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n \n throw error;\n }\n });\n }\n\n async handleSecureAnswer(answerData) {\n console.log('\uD83C\uDFAF handleSecureAnswer called with answerData:', answerData ? 'present' : 'null');\n try {\n \n if (!answerData || typeof answerData !== 'object' || Array.isArray(answerData)) {\n this._secureLog('error', 'CRITICAL: Invalid answer data structure', { \n hasAnswerData: !!answerData,\n answerDataType: typeof answerData,\n isArray: Array.isArray(answerData)\n });\n throw new Error('CRITICAL SECURITY FAILURE: Answer data must be a non-null object');\n }\n \n if (answerData.type !== 'enhanced_secure_answer' || !answerData.sdp) {\n this._secureLog('error', 'CRITICAL: Invalid answer format', { \n type: answerData.type,\n hasSdp: !!answerData.sdp\n });\n throw new Error('CRITICAL SECURITY FAILURE: Invalid answer format - hard abort required');\n }\n\n // CRITICAL: Strict validation of ECDH public key structure\n if (!answerData.ecdhPublicKey || typeof answerData.ecdhPublicKey !== 'object' || Array.isArray(answerData.ecdhPublicKey)) {\n this._secureLog('error', 'CRITICAL: Invalid ECDH public key structure in answer', { \n hasEcdhKey: !!answerData.ecdhPublicKey,\n ecdhKeyType: typeof answerData.ecdhPublicKey,\n isArray: Array.isArray(answerData.ecdhPublicKey)\n });\n throw new Error('CRITICAL SECURITY FAILURE: Missing or invalid ECDH public key structure');\n }\n \n if (!answerData.ecdhPublicKey.keyData || !answerData.ecdhPublicKey.signature) {\n this._secureLog('error', 'CRITICAL: ECDH key missing keyData or signature in answer', { \n hasKeyData: !!answerData.ecdhPublicKey.keyData,\n hasSignature: !!answerData.ecdhPublicKey.signature\n });\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key missing keyData or signature');\n }\n\n // CRITICAL: Strict validation of ECDSA public key structure\n if (!answerData.ecdsaPublicKey || typeof answerData.ecdsaPublicKey !== 'object' || Array.isArray(answerData.ecdsaPublicKey)) {\n this._secureLog('error', 'CRITICAL: Invalid ECDSA public key structure in answer', { \n hasEcdsaKey: !!answerData.ecdsaPublicKey,\n ecdsaKeyType: typeof answerData.ecdsaPublicKey,\n isArray: Array.isArray(answerData.ecdsaPublicKey)\n });\n throw new Error('CRITICAL SECURITY FAILURE: Missing or invalid ECDSA public key structure');\n }\n \n if (!answerData.ecdsaPublicKey.keyData || !answerData.ecdsaPublicKey.signature) {\n this._secureLog('error', 'CRITICAL: ECDSA key missing keyData or signature in answer', { \n hasKeyData: !!answerData.ecdsaPublicKey.keyData,\n hasSignature: !!answerData.ecdsaPublicKey.signature\n });\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key missing keyData or signature');\n }\n\n // Additional MITM protection: Validate answer data structure\n if (!answerData.timestamp || !answerData.version) {\n throw new Error('Missing required fields in response data \u2013 possible MITM attack');\n }\n\n // MITM Protection: Verify session ID if present (for enhanced security)\n if (answerData.sessionId && this.sessionId && answerData.sessionId !== this.sessionId) {\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Session ID mismatch detected - possible MITM attack', {\n expectedSessionId: this.sessionId,\n receivedSessionId: answerData.sessionId\n });\n throw new Error('Session ID mismatch \u2013 possible MITM attack');\n }\n\n // Check for replay attacks (reject answers older than 1 hour)\n const answerAge = Date.now() - answerData.timestamp;\n if (answerAge > 3600000) { // 1 hour in milliseconds\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Answer data is too old - possible replay attack', {\n answerAge: answerAge,\n timestamp: answerData.timestamp\n });\n \n // Notify the main code about the replay attack error\n if (this.onAnswerError) {\n this.onAnswerError('replay_attack', 'Response data is too old \u2013 possible replay attack');\n }\n \n throw new Error('Response data is too old \u2013 possible replay attack');\n }\n\n // Check protocol version compatibility\n if (answerData.version !== '4.0') {\n window.EnhancedSecureCryptoUtils.secureLog.log('warn', 'Incompatible protocol version in answer', {\n expectedVersion: '4.0',\n receivedVersion: answerData.version\n });\n }\n\n // Import ECDSA public key for verification (self-signed)\n const peerECDSAPublicKey = await crypto.subtle.importKey(\n 'spki',\n new Uint8Array(answerData.ecdsaPublicKey.keyData),\n {\n name: 'ECDSA',\n namedCurve: 'P-384'\n },\n false,\n ['verify']\n );\n\n\n // Now import and verify the ECDH public key using the verified ECDSA key\n const peerPublicKey = await window.EnhancedSecureCryptoUtils.importPublicKeyFromSignedPackage(\n answerData.ecdhPublicKey,\n peerECDSAPublicKey\n );\n \n // Additional MITM protection: Verify session salt integrity\n if (!this.sessionSalt || this.sessionSalt.length !== 64) {\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Invalid session salt detected - possible session hijacking', {\n saltLength: this.sessionSalt ? this.sessionSalt.length : 0\n });\n throw new Error('Invalid session salt \u2013 possible session hijacking attempt');\n }\n\n // Verify that the session salt hasn't been tampered with\n const expectedSaltHash = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(this.sessionSalt);\n window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Session salt integrity verified', {\n saltFingerprint: expectedSaltHash.substring(0, 8)\n });\n\n // Additional validation: Ensure all keys are CryptoKey instances before derivation\n if (!(this.ecdhKeyPair?.privateKey instanceof CryptoKey)) {\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Local ECDH private key is not a CryptoKey in handleSecureAnswer', {\n hasKeyPair: !!this.ecdhKeyPair,\n privateKeyType: typeof this.ecdhKeyPair?.privateKey,\n privateKeyAlgorithm: this.ecdhKeyPair?.privateKey?.algorithm?.name\n });\n throw new Error('Local ECDH private key is not a CryptoKey');\n }\n \n if (!(peerPublicKey instanceof CryptoKey)) {\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Peer ECDH public key is not a CryptoKey in handleSecureAnswer', {\n publicKeyType: typeof peerPublicKey,\n publicKeyAlgorithm: peerPublicKey?.algorithm?.name\n });\n throw new Error('Peer ECDH public key is not a CryptoKey');\n }\n\n // Store peer's public key for PFS key rotation\n this.peerPublicKey = peerPublicKey;\n \n // Initialize connection ID if not already set\n if (!this.connectionId) {\n this.connectionId = Array.from(crypto.getRandomValues(new Uint8Array(8)))\n .map(b => b.toString(16).padStart(2, '0')).join('');\n }\n\n \n const derivedKeys = await window.EnhancedSecureCryptoUtils.deriveSharedKeys(\n this.ecdhKeyPair.privateKey,\n peerPublicKey,\n this.sessionSalt\n );\n \n this.encryptionKey = derivedKeys.encryptionKey;\n this.macKey = derivedKeys.macKey;\n this.metadataKey = derivedKeys.metadataKey;\n this.keyFingerprint = derivedKeys.fingerprint;\n this.sequenceNumber = 0;\n this.expectedSequenceNumber = 0;\n this.messageCounter = 0;\n this.processedMessageIds.clear();\n this.replayWindow.clear(); // Clear replay window\n // Validate that all keys are properly set\n if (!(this.encryptionKey instanceof CryptoKey) || \n !(this.macKey instanceof CryptoKey) || \n !(this.metadataKey instanceof CryptoKey)) {\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Invalid key types after derivation in handleSecureAnswer', {\n encryptionKeyType: typeof this.encryptionKey,\n macKeyType: typeof this.macKey,\n metadataKeyType: typeof this.metadataKey,\n encryptionKeyAlgorithm: this.encryptionKey?.algorithm?.name,\n macKeyAlgorithm: this.macKey?.algorithm?.name,\n metadataKeyAlgorithm: this.metadataKey?.algorithm?.name\n });\n throw new Error('Invalid key types after export');\n }\n \n this._secureLog('info', 'Encryption keys set in handleSecureAnswer', {\n hasEncryptionKey: !!this.encryptionKey,\n hasMacKey: !!this.macKey,\n hasMetadataKey: !!this.metadataKey,\n hasKeyFingerprint: !!this.keyFingerprint,\n mitmProtection: 'enabled',\n signatureVerified: true\n });\n \n // Update security features for initiator after successful key exchange\n this.securityFeatures.hasMutualAuth = true;\n this.securityFeatures.hasMetadataProtection = true;\n this.securityFeatures.hasEnhancedReplayProtection = true;\n this.securityFeatures.hasPFS = true;\n \n // PFS: Initialize key version tracking\n this.currentKeyVersion = 0;\n this.lastKeyRotation = Date.now();\n this.keyVersions.set(0, {\n salt: this.sessionSalt,\n timestamp: this.lastKeyRotation,\n messageCount: 0\n });\n \n this.onKeyExchange(this.keyFingerprint);\n\n // Compute SAS for MITM protection (Offer side - Answer handler)\n try {\n console.log('Starting SAS computation for Offer side (Answer handler)');\n const remoteFP = this._extractDTLSFingerprintFromSDP(answerData.sdp); // \u0443\u0436\u0435 \u0435\u0441\u0442\u044C \u0432 \u043A\u043E\u0434\u0435\n const localFP = this.expectedDTLSFingerprint; // \u0442\u044B \u0435\u0433\u043E \u0441\u043E\u0445\u0440\u0430\u043D\u044F\u0435\u0448\u044C \u043F\u0440\u0438 \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u0438 \u043E\u0444\u0444\u0435\u0440\u0430/\u043E\u0442\u0432\u0435\u0442\u0430\n const keyBytes = this._decodeKeyFingerprint(this.keyFingerprint); // \u0443\u0442\u0438\u043B\u0438\u0442\u0430 \u0434\u0435\u043A\u043E\u0434\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F\n console.log('SAS computation parameters:', { \n remoteFP: remoteFP ? remoteFP.substring(0, 16) + '...' : 'null/undefined', \n localFP: localFP ? localFP.substring(0, 16) + '...' : 'null/undefined', \n keyBytesLength: keyBytes ? keyBytes.length : 'null/undefined',\n keyBytesType: keyBytes ? keyBytes.constructor.name : 'null/undefined'\n });\n\n this.verificationCode = await this._computeSAS(keyBytes, localFP, remoteFP);\n this.onStatusChange?.('verifying'); // \u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C SAS \u0438 \u0436\u0434\u0451\u043C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u044F\n this.onVerificationRequired(this.verificationCode);\n \n // CRITICAL: Store SAS code to send when data channel opens\n this.pendingSASCode = this.verificationCode;\n console.log('\uD83D\uDCE4 SAS code ready to send when data channel opens:', this.verificationCode);\n \n this._secureLog('info', 'SAS verification code generated for MITM protection (Offer side)', {\n sasCode: this.verificationCode,\n localFP: localFP.substring(0, 16) + '...',\n remoteFP: remoteFP.substring(0, 16) + '...',\n timestamp: Date.now()\n });\n } catch (sasError) {\n console.error('SAS computation failed in handleSecureAnswer (Offer side):', sasError);\n this._secureLog('error', 'SAS computation failed in handleSecureAnswer (Offer side)', {\n error: sasError.message,\n stack: sasError.stack,\n timestamp: Date.now()\n });\n }\n\n // Validate DTLS fingerprint before setting remote description\n if (this.strictDTLSValidation) {\n try {\n const receivedFingerprint = this._extractDTLSFingerprintFromSDP(answerData.sdp);\n \n if (this.expectedDTLSFingerprint) {\n this._validateDTLSFingerprint(receivedFingerprint, this.expectedDTLSFingerprint, 'answer_validation');\n } else {\n // Store fingerprint for future validation (first connection)\n this.expectedDTLSFingerprint = receivedFingerprint;\n this._secureLog('info', 'Stored DTLS fingerprint for future validation', {\n fingerprint: receivedFingerprint,\n context: 'first_connection'\n });\n }\n } catch (error) {\n this._secureLog('warn', 'DTLS fingerprint validation failed - continuing in fallback mode', { \n error: error.message,\n context: 'answer_validation'\n });\n\n }\n } else {\n this._secureLog('info', 'DTLS fingerprint validation disabled - proceeding without validation');\n }\n\n this._secureLog('debug', 'Setting remote description from answer', {\n sdpLength: answerData.sdp?.length || 0\n });\n \n await this.peerConnection.setRemoteDescription({\n type: 'answer',\n sdp: answerData.sdp\n });\n \n this._secureLog('debug', 'Remote description set successfully from answer', {\n signalingState: this.peerConnection.signalingState\n });\n \n console.log('Enhanced secure connection established');\n\n setTimeout(async () => {\n try {\n const securityData = await this.calculateAndReportSecurityLevel();\n if (securityData) {\n console.log('\u2705 Security level calculated after connection:', securityData.level);\n this.notifySecurityUpdate();\n }\n } catch (error) {\n this._secureLog('error', '\u274C Error calculating security after connection:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n }, 1000);\n setTimeout(async () => {\n if (!this.lastSecurityCalculation || this.lastSecurityCalculation.score < 50) {\n console.log('\uD83D\uDD04 Retrying security calculation...');\n await this.calculateAndReportSecurityLevel();\n this.notifySecurityUpdate();\n }\n }, 3000);\n this.notifySecurityUpdate();\n } catch (error) {\n this._secureLog('error', 'Enhanced secure answer handling failed', {\n errorType: error.constructor.name\n });\n this.onStatusChange('failed');\n\n if (this.onAnswerError) {\n if (error.message.includes('too old') || error.message.includes('\u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0441\u0442\u0430\u0440\u044B\u0435')) {\n this.onAnswerError('replay_attack', error.message);\n } else if (error.message.includes('MITM') || error.message.includes('signature') || error.message.includes('\u043F\u043E\u0434\u043F\u0438\u0441\u044C')) {\n this.onAnswerError('security_violation', error.message);\n } else {\n this.onAnswerError('general_error', error.message);\n }\n }\n \n throw error;\n }\n }\n\n forceSecurityUpdate() {\n console.log('\uD83D\uDD04 Force security update requested');\n setTimeout(async () => {\n try {\n const securityData = await this.calculateAndReportSecurityLevel();\n if (securityData) {\n this.notifySecurityUpdate();\n console.log('\u2705 Force security update completed');\n }\n } catch (error) {\n this._secureLog('error', '\u274C Force security update failed:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n }, 100);\n }\n\n initiateVerification() {\n \n if (this.isInitiator) {\n // Ensure verification initiation notice wasn't already sent\n if (!this.verificationInitiationSent) {\n this.verificationInitiationSent = true;\n this.deliverMessageToUI('\uD83D\uDD10 CRITICAL: Compare verification code with peer out-of-band (voice/video/in-person) to prevent MITM attack!', 'system');\n this.deliverMessageToUI(`\uD83D\uDD10 Your verification code: ${this.verificationCode}`, 'system');\n this.deliverMessageToUI('\uD83D\uDD10 Ask peer to confirm this exact code before allowing traffic!', 'system');\n }\n } else {\n // Answer side: Wait for SAS code from Offer side\n console.log('\uD83D\uDCE5 Answer side: Waiting for SAS code from Offer side');\n this.deliverMessageToUI('\uD83D\uDCE5 Waiting for verification code from peer...', 'system');\n }\n }\n\n confirmVerification() {\n \n try {\n console.log('\uD83D\uDCE4 confirmVerification - sending local confirmation');\n \n // Mark local verification as confirmed\n this.localVerificationConfirmed = true;\n \n // Send confirmation to peer\n const confirmationPayload = {\n type: 'verification_confirmed',\n data: {\n timestamp: Date.now(),\n verificationMethod: 'SAS',\n securityLevel: 'MITM_PROTECTION_REQUIRED'\n }\n };\n \n console.log('\uD83D\uDCE4 Sending verification confirmation:', confirmationPayload);\n this.dataChannel.send(JSON.stringify(confirmationPayload));\n \n // Notify UI about state change\n if (this.onVerificationStateChange) {\n this.onVerificationStateChange({\n localConfirmed: this.localVerificationConfirmed,\n remoteConfirmed: this.remoteVerificationConfirmed,\n bothConfirmed: this.bothVerificationsConfirmed\n });\n }\n \n // Check if both parties have confirmed\n this._checkBothVerificationsConfirmed();\n \n // Notify UI about local confirmation\n this.deliverMessageToUI('\u2705 You confirmed the verification code. Waiting for peer confirmation...', 'system');\n \n this.processMessageQueue();\n } catch (error) {\n this._secureLog('error', '\u274C SAS verification failed:', { errorType: error?.constructor?.name || 'Unknown' });\n this.deliverMessageToUI('\u274C SAS verification failed', 'system');\n }\n }\n\n _checkBothVerificationsConfirmed() {\n // Check if both parties have confirmed verification\n if (this.localVerificationConfirmed && this.remoteVerificationConfirmed && !this.bothVerificationsConfirmed) {\n console.log('\uD83C\uDF89 Both parties confirmed verification!');\n this.bothVerificationsConfirmed = true;\n \n // Notify both parties that verification is complete\n const bothConfirmedPayload = {\n type: 'verification_both_confirmed',\n data: {\n timestamp: Date.now(),\n verificationMethod: 'SAS',\n securityLevel: 'MITM_PROTECTION_COMPLETE'\n }\n };\n \n console.log('\uD83D\uDCE4 Sending both confirmed notification:', bothConfirmedPayload);\n this.dataChannel.send(JSON.stringify(bothConfirmedPayload));\n \n // Notify UI about state change\n if (this.onVerificationStateChange) {\n this.onVerificationStateChange({\n localConfirmed: this.localVerificationConfirmed,\n remoteConfirmed: this.remoteVerificationConfirmed,\n bothConfirmed: this.bothVerificationsConfirmed\n });\n }\n \n // Set verified status and open chat after 2 second delay\n this.deliverMessageToUI('\uD83C\uDF89 Both parties confirmed! Opening secure chat in 2 seconds...', 'system');\n \n setTimeout(() => {\n this._setVerifiedStatus(true, 'MUTUAL_SAS_CONFIRMED', { \n code: this.verificationCode,\n timestamp: Date.now()\n });\n this._enforceVerificationGate('mutual_confirmed', false);\n this.onStatusChange?.('verified');\n }, 2000);\n }\n }\n\n handleVerificationConfirmed(data) {\n // Handle peer's verification confirmation\n console.log('\uD83D\uDCE5 Received verification confirmation from peer');\n this.remoteVerificationConfirmed = true;\n \n // Notify UI about peer confirmation\n this.deliverMessageToUI('\u2705 Peer confirmed the verification code. Waiting for your confirmation...', 'system');\n \n // Notify UI about state change\n if (this.onVerificationStateChange) {\n this.onVerificationStateChange({\n localConfirmed: this.localVerificationConfirmed,\n remoteConfirmed: this.remoteVerificationConfirmed,\n bothConfirmed: this.bothVerificationsConfirmed\n });\n }\n \n // Check if both parties have confirmed\n this._checkBothVerificationsConfirmed();\n }\n\n handleVerificationBothConfirmed(data) {\n // Handle notification that both parties have confirmed\n console.log('\uD83D\uDCE5 Received both confirmed notification from peer');\n this.bothVerificationsConfirmed = true;\n \n // Notify UI about state change\n if (this.onVerificationStateChange) {\n this.onVerificationStateChange({\n localConfirmed: this.localVerificationConfirmed,\n remoteConfirmed: this.remoteVerificationConfirmed,\n bothConfirmed: this.bothVerificationsConfirmed\n });\n }\n \n // Set verified status and open chat after 2 second delay\n this.deliverMessageToUI('\uD83C\uDF89 Both parties confirmed! Opening secure chat in 2 seconds...', 'system');\n \n setTimeout(() => {\n this._setVerifiedStatus(true, 'MUTUAL_SAS_CONFIRMED', { \n code: this.verificationCode,\n timestamp: Date.now()\n });\n this._enforceVerificationGate('mutual_confirmed', false);\n this.onStatusChange?.('verified');\n }, 2000);\n }\n\n handleVerificationRequest(data) {\n \n console.log('\uD83D\uDD0D handleVerificationRequest called with:');\n console.log(' - receivedCode:', data.code, '(type:', typeof data.code, ')');\n console.log(' - expectedCode:', this.verificationCode, '(type:', typeof this.verificationCode, ')');\n console.log(' - codesMatch:', data.code === this.verificationCode);\n console.log(' - data object:', data);\n \n if (data.code === this.verificationCode) {\n // \u2705 SAS verification successful - MITM protection confirmed\n const responsePayload = {\n type: 'verification_response',\n data: {\n ok: true,\n timestamp: Date.now(),\n verificationMethod: 'SAS', // Indicate SAS was used\n securityLevel: 'MITM_PROTECTED'\n }\n };\n this.dataChannel.send(JSON.stringify(responsePayload));\n \n // Ensure verification success notice wasn't already sent\n if (!this.verificationNotificationSent) {\n this.verificationNotificationSent = true;\n this.deliverMessageToUI('\u2705 SAS verification successful! MITM protection confirmed. Channel is now secure!', 'system');\n }\n \n this.processMessageQueue();\n } else {\n // \u274C SAS verification failed - possible MITM attack\n console.log('\u274C SAS verification failed - codes do not match, disconnecting');\n const responsePayload = {\n type: 'verification_response',\n data: {\n ok: false,\n timestamp: Date.now(),\n reason: 'code_mismatch'\n }\n };\n this.dataChannel.send(JSON.stringify(responsePayload));\n \n this._secureLog('error', 'SAS verification failed - possible MITM attack', {\n receivedCode: data.code,\n expectedCode: this.verificationCode,\n timestamp: Date.now()\n });\n \n this.deliverMessageToUI('\u274C SAS verification failed! Possible MITM attack detected. Connection aborted for safety!', 'system');\n this.disconnect();\n }\n }\n\n handleSASCode(data) {\n \n console.log('\uD83D\uDCE5 Received SAS code from Offer side:', data.code);\n \n this.verificationCode = data.code;\n this.onStatusChange?.('verifying'); // \u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C SAS \u0438 \u0436\u0434\u0451\u043C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u044F\n this.onVerificationRequired(this.verificationCode);\n \n this._secureLog('info', 'SAS code received from Offer side', {\n sasCode: this.verificationCode,\n timestamp: Date.now()\n });\n }\n\n handleVerificationResponse(data) {\n \n if (data.ok === true) {\n \n // Log successful mutual SAS verification\n this._secureLog('info', 'Mutual SAS verification completed - MITM protection active', {\n verificationMethod: data.verificationMethod || 'SAS',\n securityLevel: data.securityLevel || 'MITM_PROTECTED',\n timestamp: Date.now()\n });\n \n // Ensure verification success notice wasn't already sent\n if (!this.verificationNotificationSent) {\n this.verificationNotificationSent = true;\n this.deliverMessageToUI('\u2705 Mutual SAS verification complete! MITM protection active. Channel is now secure!', 'system');\n }\n \n this.processMessageQueue();\n } else {\n // \u274C Peer verification failed - connection not secure\n this._secureLog('error', 'Peer SAS verification failed - connection not secure', {\n responseData: data,\n timestamp: Date.now()\n });\n \n this.deliverMessageToUI('\u274C Peer verification failed! Connection not secure!', 'system');\n this.disconnect();\n }\n }\n\n validateOfferData(offerData) {\n return offerData &&\n offerData.type === 'enhanced_secure_offer' &&\n offerData.sdp &&\n offerData.publicKey &&\n offerData.salt &&\n offerData.verificationCode &&\n Array.isArray(offerData.publicKey) &&\n Array.isArray(offerData.salt) &&\n offerData.salt.length === 32;\n }\n\n validateEnhancedOfferData(offerData) {\n console.log('\uD83C\uDFAF validateEnhancedOfferData called with:', offerData ? 'valid object' : 'null/undefined');\n try {\n // CRITICAL: Strict type checking to prevent syntax errors\n if (!offerData || typeof offerData !== 'object' || Array.isArray(offerData)) {\n this._secureLog('error', 'CRITICAL: Invalid offer data structure', { \n hasOfferData: !!offerData,\n offerDataType: typeof offerData,\n isArray: Array.isArray(offerData)\n });\n throw new Error('CRITICAL SECURITY FAILURE: Offer data must be a non-null object');\n }\n\n // Basic required fields for all versions\n const basicFields = ['type', 'sdp'];\n for (const field of basicFields) {\n if (!offerData[field]) {\n throw new Error(`Missing required field: ${field}`);\n }\n }\n\n // Validate offer type (support both v3.0 and v4.0 formats)\n if (!['enhanced_secure_offer', 'secure_offer'].includes(offerData.type)) {\n throw new Error('Invalid offer type');\n }\n\n // Check if this is v4.0 format with enhanced features\n const isV4Format = offerData.version === '4.0' && offerData.ecdhPublicKey && offerData.ecdsaPublicKey;\n \n if (isV4Format) {\n // v4.0 enhanced validation\n const v4RequiredFields = [\n 'ecdhPublicKey', 'ecdsaPublicKey', 'salt', 'verificationCode',\n 'authChallenge', 'timestamp', 'version', 'securityLevel'\n ];\n\n for (const field of v4RequiredFields) {\n if (!offerData[field]) {\n throw new Error(`Missing v4.0 field: ${field}`);\n }\n }\n\n // Validate salt (must be 64 bytes for v4.0)\n if (!Array.isArray(offerData.salt) || offerData.salt.length !== 64) {\n throw new Error('Salt must be exactly 64 bytes for v4.0');\n }\n\n // Validate timestamp (not older than 1 hour)\n const offerAge = Date.now() - offerData.timestamp;\n if (offerAge > 3600000) {\n throw new Error('Offer is too old (older than 1 hour)');\n }\n\n // CRITICAL: Strict validation of key structures to prevent syntax errors\n if (!offerData.ecdhPublicKey || typeof offerData.ecdhPublicKey !== 'object' || Array.isArray(offerData.ecdhPublicKey)) {\n this._secureLog('error', 'CRITICAL: Invalid ECDH public key structure', { \n hasEcdhKey: !!offerData.ecdhPublicKey,\n ecdhKeyType: typeof offerData.ecdhPublicKey,\n isArray: Array.isArray(offerData.ecdhPublicKey)\n });\n throw new Error('CRITICAL SECURITY FAILURE: Invalid ECDH public key structure - hard abort required');\n }\n\n if (!offerData.ecdsaPublicKey || typeof offerData.ecdsaPublicKey !== 'object' || Array.isArray(offerData.ecdsaPublicKey)) {\n this._secureLog('error', 'CRITICAL: Invalid ECDSA public key structure', { \n hasEcdsaKey: !!offerData.ecdsaPublicKey,\n ecdsaKeyType: typeof offerData.ecdsaPublicKey,\n isArray: Array.isArray(offerData.ecdsaPublicKey)\n });\n throw new Error('CRITICAL SECURITY FAILURE: Invalid ECDSA public key structure - hard abort required');\n }\n\n // CRITICAL: Validate key internal structure to prevent syntax errors\n if (!offerData.ecdhPublicKey.keyData || !offerData.ecdhPublicKey.signature) {\n this._secureLog('error', 'CRITICAL: ECDH key missing keyData or signature', { \n hasKeyData: !!offerData.ecdhPublicKey.keyData,\n hasSignature: !!offerData.ecdhPublicKey.signature\n });\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key missing keyData or signature');\n }\n\n if (!offerData.ecdsaPublicKey.keyData || !offerData.ecdsaPublicKey.signature) {\n this._secureLog('error', 'CRITICAL: ECDSA key missing keyData or signature', { \n hasKeyData: !!offerData.ecdsaPublicKey.keyData,\n hasSignature: !!offerData.ecdsaPublicKey.signature\n });\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key missing keyData or signature');\n }\n\n if (typeof offerData.verificationCode !== 'string' || offerData.verificationCode.length < 6) {\n throw new Error('Invalid SAS verification code format - MITM protection required');\n }\n\n this._secureLog('info', 'v4.0 offer validation passed', {\n version: offerData.version,\n hasSecurityLevel: !!offerData.securityLevel?.level,\n offerAge: Math.round(offerAge / 1000) + 's'\n });\n } else {\n // v3.0 backward compatibility validation\n // NOTE: v3.0 has limited security - SAS verification is still critical\n const v3RequiredFields = ['publicKey', 'salt', 'verificationCode'];\n for (const field of v3RequiredFields) {\n if (!offerData[field]) {\n throw new Error(`Missing v3.0 field: ${field}`);\n }\n }\n\n // Validate salt (32 bytes for v3.0)\n if (!Array.isArray(offerData.salt) || offerData.salt.length !== 32) {\n throw new Error('Salt must be exactly 32 bytes for v3.0');\n }\n\n // Validate public key\n if (!Array.isArray(offerData.publicKey)) {\n throw new Error('Invalid public key format for v3.0');\n }\n\n window.EnhancedSecureCryptoUtils.secureLog.log('info', 'v3.0 offer validation passed (backward compatibility)', {\n version: 'v3.0',\n legacy: true\n });\n }\n\n // Validate SDP structure (basic check for all versions)\n if (typeof offerData.sdp !== 'string' || !offerData.sdp.includes('v=0')) {\n throw new Error('Invalid SDP structure');\n }\n\n console.log('\uD83C\uDFAF validateEnhancedOfferData completed successfully');\n return true;\n } catch (error) {\n console.log('\uD83C\uDFAF validateEnhancedOfferData ERROR:', error.message);\n this._secureLog('error', 'CRITICAL: Security validation failed - hard abort required', {\n error: error.message,\n errorType: error.constructor.name,\n timestamp: Date.now()\n });\n\n throw new Error(`CRITICAL SECURITY VALIDATION FAILURE: ${error.message}`);\n }\n }\n\n async sendSecureMessage(message) {\n // Comprehensive input validation\n const validation = this._validateInputData(message, 'sendSecureMessage');\n if (!validation.isValid) {\n const errorMessage = `Input validation failed: ${validation.errors.join(', ')}`;\n this._secureLog('error', '\u274C Input validation failed in sendSecureMessage', {\n errors: validation.errors,\n messageType: typeof message\n });\n throw new Error(errorMessage);\n }\n\n // Rate limiting check\n if (!this._checkRateLimit('sendSecureMessage')) {\n throw new Error('Rate limit exceeded for secure message sending');\n }\n\n // Enforce verification gate\n this._enforceVerificationGate('sendSecureMessage');\n\n // Quick readiness check WITHOUT mutex\n if (!this.isConnected()) {\n if (validation.sanitizedData && typeof validation.sanitizedData === 'object' && validation.sanitizedData.type && validation.sanitizedData.type.startsWith('file_')) {\n throw new Error('Connection not ready for file transfer. Please ensure the connection is established and verified.');\n }\n this.messageQueue.push(validation.sanitizedData);\n throw new Error('Connection not ready. Message queued for sending.');\n }\n \n // Use mutex ONLY for cryptographic operations\n return this._withMutex('cryptoOperation', async (operationId) => {\n // Re-check inside critical section\n if (!this.isConnected() || !this.isVerified) {\n throw new Error('Connection lost during message preparation');\n }\n \n // Validate keys inside critical section\n if (!this.encryptionKey || !this.macKey || !this.metadataKey) {\n throw new Error('Encryption keys not initialized');\n }\n \n // Additional rate limiting check\n if (!window.EnhancedSecureCryptoUtils.rateLimiter.checkMessageRate(this.rateLimiterId)) {\n throw new Error('Message rate limit exceeded (60 messages per minute)');\n }\n \n try {\n // Accept strings and objects; stringify objects\n const textToSend = typeof validation.sanitizedData === 'string' ? validation.sanitizedData : JSON.stringify(validation.sanitizedData);\n const sanitizedMessage = window.EnhancedSecureCryptoUtils.sanitizeMessage(textToSend);\n const messageId = `msg_${Date.now()}_${this.messageCounter++}`;\n \n // Create AAD with sequence number for anti-replay protection\n if (typeof this._createMessageAAD !== 'function') {\n throw new Error('_createMessageAAD method is not available in sendSecureMessage. Manager may not be fully initialized.');\n }\n const aad = message.aad || this._createMessageAAD('enhanced_message', { content: sanitizedMessage });\n \n // Use enhanced encryption with AAD and sequence number\n const encryptedData = await window.EnhancedSecureCryptoUtils.encryptMessage(\n sanitizedMessage,\n this.encryptionKey,\n this.macKey,\n this.metadataKey,\n messageId,\n JSON.parse(aad).sequenceNumber // Use sequence number from AAD\n );\n \n const payload = {\n type: 'enhanced_message',\n data: encryptedData,\n keyVersion: this.currentKeyVersion,\n version: '4.0'\n };\n \n this.dataChannel.send(JSON.stringify(payload));\n // Locally display only plain strings to avoid UI duplication\n if (typeof validation.sanitizedData === 'string') {\n this.deliverMessageToUI(validation.sanitizedData, 'sent');\n }\n \n this._secureLog('debug', '\uD83D\uDCE4 Secure message sent successfully', {\n operationId: operationId,\n messageLength: sanitizedMessage.length,\n keyVersion: this.currentKeyVersion\n });\n \n } catch (error) {\n this._secureLog('error', '\u274C Secure message sending failed', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n throw error;\n }\n }, 2000); // Reduced timeout for crypto operations\n }\n\n processMessageQueue() {\n while (this.messageQueue.length > 0 && this.isConnected() && this.isVerified) {\n const message = this.messageQueue.shift();\n this.sendSecureMessage(message).catch(console.error);\n }\n }\n\n startHeartbeat() {\n // Heartbeat moved to unified scheduler with connection validation\n this._secureLog('info', '\uD83D\uDD27 Heartbeat moved to unified scheduler');\n \n // Store heartbeat configuration for scheduler\n this._heartbeatConfig = {\n enabled: true,\n interval: EnhancedSecureWebRTCManager.TIMEOUTS.HEARTBEAT_INTERVAL,\n lastHeartbeat: 0\n };\n }\n\n stopHeartbeat() {\n // Heartbeat stopped via unified scheduler\n if (this._heartbeatConfig) {\n this._heartbeatConfig.enabled = false;\n }\n }\n\n /**\n * Stop all active timers and cleanup scheduler\n */\n _stopAllTimers() {\n this._secureLog('info', '\uD83D\uDD27 Stopping all timers and cleanup scheduler');\n \n // Stop maintenance scheduler\n if (this._maintenanceScheduler) {\n clearInterval(this._maintenanceScheduler);\n this._maintenanceScheduler = null;\n }\n \n // Stop heartbeat\n if (this._heartbeatConfig) {\n this._heartbeatConfig.enabled = false;\n }\n \n // Clear all timer references\n if (this._activeTimers) {\n this._activeTimers.forEach(timer => {\n if (timer) clearInterval(timer);\n });\n this._activeTimers.clear();\n }\n \n this._secureLog('info', '\u2705 All timers stopped successfully');\n }\n\n handleHeartbeat() {\n console.log('Heartbeat received - connection alive');\n }\n\n waitForIceGathering() {\n return new Promise((resolve) => {\n if (this.peerConnection.iceGatheringState === 'complete') {\n resolve();\n return;\n }\n\n const checkState = () => {\n if (this.peerConnection && this.peerConnection.iceGatheringState === 'complete') {\n this.peerConnection.removeEventListener('icegatheringstatechange', checkState);\n resolve();\n }\n };\n \n this.peerConnection.addEventListener('icegatheringstatechange', checkState);\n \n setTimeout(() => {\n if (this.peerConnection) {\n this.peerConnection.removeEventListener('icegatheringstatechange', checkState);\n }\n resolve();\n }, EnhancedSecureWebRTCManager.TIMEOUTS.ICE_GATHERING_TIMEOUT);\n });\n }\n\n retryConnection() {\n console.log(`Retrying connection (attempt ${this.connectionAttempts}/${this.maxConnectionAttempts})`);\n this.onStatusChange('retrying');\n }\n\n isConnected() {\n const hasDataChannel = !!this.dataChannel;\n const dataChannelState = this.dataChannel?.readyState;\n const isDataChannelOpen = dataChannelState === 'open';\n const isVerified = this.isVerified;\n const connectionState = this.peerConnection?.connectionState;\n \n return this.dataChannel && this.dataChannel.readyState === 'open' && this.isVerified;\n }\n\n getConnectionInfo() {\n return {\n fingerprint: this.keyFingerprint,\n isConnected: this.isConnected(),\n isVerified: this.isVerified,\n connectionState: this.peerConnection?.connectionState,\n iceConnectionState: this.peerConnection?.iceConnectionState,\n verificationCode: this.verificationCode\n };\n }\n\n disconnect() {\n // Stop all timers first\n this._stopAllTimers();\n \n if (this.fileTransferSystem) {\n this.fileTransferSystem.cleanup();\n }\n this.intentionalDisconnect = true;\n \n window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Starting intentional disconnect');\n\n this.sendDisconnectNotification();\n\n setTimeout(() => {\n this.sendDisconnectNotification(); \n }, 100);\n\n document.dispatchEvent(new CustomEvent('peer-disconnect', {\n detail: { \n reason: 'user_disconnect',\n timestamp: Date.now()\n }\n }));\n }\n \n handleUnexpectedDisconnect() {\n this.sendDisconnectNotification();\n this.isVerified = false;\n \n // Ensure disconnect notification wasn't already sent\n if (!this.disconnectNotificationSent) {\n this.disconnectNotificationSent = true;\n this.deliverMessageToUI('\uD83D\uDD0C Connection lost. Attempting to reconnect...', 'system');\n }\n \n // Cleanup file transfer system on unexpected disconnect\n if (this.fileTransferSystem) {\n console.log('\uD83E\uDDF9 Cleaning up file transfer system on unexpected disconnect...');\n this.fileTransferSystem.cleanup();\n this.fileTransferSystem = null;\n }\n \n document.dispatchEvent(new CustomEvent('peer-disconnect', {\n detail: { \n reason: 'connection_lost',\n timestamp: Date.now()\n }\n }));\n\n }\n \n sendDisconnectNotification() {\n try {\n if (this.dataChannel && this.dataChannel.readyState === 'open') {\n const notification = {\n type: 'peer_disconnect',\n timestamp: Date.now(),\n reason: this.intentionalDisconnect ? 'user_disconnect' : 'connection_lost'\n };\n\n for (let i = 0; i < 3; i++) {\n try {\n this.dataChannel.send(JSON.stringify(notification));\n window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Disconnect notification sent', {\n reason: notification.reason,\n attempt: i + 1\n });\n break;\n } catch (sendError) {\n if (i === 2) { \n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Failed to send disconnect notification', {\n error: sendError.message\n });\n }\n }\n }\n }\n } catch (error) {\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Could not send disconnect notification', {\n error: error.message\n });\n }\n }\n \n attemptReconnection() {\n // Ensure reconnection-failed notification wasn't already sent\n if (!this.reconnectionFailedNotificationSent) {\n this.reconnectionFailedNotificationSent = true;\n this.deliverMessageToUI('\u274C Unable to reconnect. A new connection is required.', 'system');\n }\n\n }\n \n handlePeerDisconnectNotification(data) {\n const reason = data.reason || 'unknown';\n const reasonText = reason === 'user_disconnect' ? 'manually disconnected.' : 'connection lost.';\n \n // Ensure peer-disconnect notification wasn't already sent\n if (!this.peerDisconnectNotificationSent) {\n this.peerDisconnectNotificationSent = true;\n this.deliverMessageToUI(`\uD83D\uDC4B Peer ${reasonText}`, 'system');\n }\n \n this.onStatusChange('peer_disconnected');\n \n this.intentionalDisconnect = false;\n this.isVerified = false;\n this.stopHeartbeat();\n \n this.onKeyExchange(''); \n this.onVerificationRequired(''); \n\n document.dispatchEvent(new CustomEvent('peer-disconnect', {\n detail: { \n reason: reason,\n timestamp: Date.now()\n }\n }));\n\n setTimeout(() => {\n this.disconnect();\n }, 2000);\n \n window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Peer disconnect notification processed', {\n reason: reason\n });\n }\n \n /**\n * Secure disconnect with complete memory cleanup\n */\n disconnect() {\n this.stopHeartbeat();\n this.isVerified = false;\n this.processedMessageIds.clear();\n this.messageCounter = 0;\n \n // Secure cleanup of cryptographic materials\n this._secureCleanupCryptographicMaterials();\n \n // Secure wipe of PFS key versions\n this.keyVersions.clear();\n this.oldKeys.clear();\n this.currentKeyVersion = 0;\n this.lastKeyRotation = Date.now();\n \n // Reset message counters\n this.sequenceNumber = 0;\n this.expectedSequenceNumber = 0;\n this.replayWindow.clear(); // Clear replay window\n \n // Reset security features\n this.securityFeatures = {\n hasEncryption: true,\n hasECDH: true,\n hasECDSA: true, \n hasMutualAuth: true, \n hasMetadataProtection: true, \n hasEnhancedReplayProtection: true, \n hasNonExtractableKeys: true, \n hasRateLimiting: true, \n hasEnhancedValidation: true, \n hasPFS: true \n };\n \n // Close connections\n if (this.dataChannel) {\n this.dataChannel.close();\n this.dataChannel = null;\n }\n if (this.peerConnection) {\n this.peerConnection.close();\n this.peerConnection = null;\n }\n \n // Secure wipe of message queue\n if (this.messageQueue && this.messageQueue.length > 0) {\n this.messageQueue.forEach((message, index) => {\n this._secureWipeMemory(message, `messageQueue[${index}]`);\n });\n this.messageQueue = [];\n }\n \n // Force garbage collection\n this._forceGarbageCollection();\n \n document.dispatchEvent(new CustomEvent('connection-cleaned', {\n detail: { \n timestamp: Date.now(),\n reason: this.intentionalDisconnect ? 'user_cleanup' : 'automatic_cleanup'\n }\n }));\n\n // Notify UI about complete cleanup\n this.onStatusChange('disconnected');\n this.onKeyExchange('');\n this.onVerificationRequired('');\n \n this._secureLog('info', '\uD83D\uDD12 Connection securely cleaned up with complete memory wipe');\n \n // Reset the intentional disconnect flag\n this.intentionalDisconnect = false;\n }\n // Public method to send files\n async sendFile(file) {\n // Enforce verification gate for file transfers\n this._enforceVerificationGate('sendFile');\n \n if (!this.isConnected()) {\n throw new Error('Connection not ready for file transfer. Please ensure the connection is established.');\n }\n\n if (!this.fileTransferSystem) {\n console.log('\uD83D\uDD04 File transfer system not initialized, attempting to initialize...');\n this.initializeFileTransfer();\n \n // Allow time for initialization\n await new Promise(resolve => setTimeout(resolve, 500));\n \n if (!this.fileTransferSystem) {\n throw new Error('File transfer system could not be initialized. Please try reconnecting.');\n }\n }\n\n // Verify key readiness\n if (!this.encryptionKey || !this.macKey) {\n throw new Error('Encryption keys not ready. Please wait for connection to be fully established.');\n }\n\n // Debug logging for file transfer system\n console.log('\uD83D\uDD0D Debug: File transfer system in sendFile:', {\n hasFileTransferSystem: !!this.fileTransferSystem,\n fileTransferSystemType: this.fileTransferSystem.constructor?.name,\n hasWebrtcManager: !!this.fileTransferSystem.webrtcManager,\n webrtcManagerType: this.fileTransferSystem.webrtcManager?.constructor?.name\n });\n\n try {\n console.log('\uD83D\uDE80 Starting file transfer for:', file.name, `(${(file.size / 1024 / 1024).toFixed(2)} MB)`);\n const fileId = await this.fileTransferSystem.sendFile(file);\n console.log('\u2705 File transfer initiated successfully with ID:', fileId);\n return fileId;\n } catch (error) {\n this._secureLog('error', '\u274C File transfer error:', { errorType: error?.constructor?.name || 'Unknown' });\n \n // Re-throw with a clearer message\n if (error.message.includes('Connection not ready')) {\n throw new Error('Connection not ready for file transfer. Check connection status.');\n } else if (error.message.includes('Encryption keys not initialized')) {\n throw new Error('Encryption keys not initialized. Try reconnecting.');\n } else if (error.message.includes('Transfer timeout')) {\n throw new Error('File transfer timeout. Check connection and try again.');\n } else {\n throw error;\n }\n }\n }\n\n // Get active file transfers\n getFileTransfers() {\n if (!this.fileTransferSystem) {\n return { sending: [], receiving: [] };\n }\n \n try {\n // Check available methods in file transfer system\n let sending = [];\n let receiving = [];\n \n if (typeof this.fileTransferSystem.getActiveTransfers === 'function') {\n sending = this.fileTransferSystem.getActiveTransfers();\n } else {\n this._secureLog('warn', '\u26A0\uFE0F getActiveTransfers method not available in file transfer system');\n }\n \n if (typeof this.fileTransferSystem.getReceivingTransfers === 'function') {\n receiving = this.fileTransferSystem.getReceivingTransfers();\n } else {\n this._secureLog('warn', '\u26A0\uFE0F getReceivingTransfers method not available in file transfer system');\n }\n \n return {\n sending: sending || [],\n receiving: receiving || []\n };\n } catch (error) {\n this._secureLog('error', '\u274C Error getting file transfers:', { errorType: error?.constructor?.name || 'Unknown' });\n return { sending: [], receiving: [] };\n }\n }\n\n // Get file transfer system status\n getFileTransferStatus() {\n if (!this.fileTransferSystem) {\n return {\n initialized: false,\n status: 'not_initialized',\n message: 'File transfer system not initialized'\n };\n }\n \n const activeTransfers = this.fileTransferSystem.getActiveTransfers();\n const receivingTransfers = this.fileTransferSystem.getReceivingTransfers();\n \n return {\n initialized: true,\n status: 'ready',\n activeTransfers: activeTransfers.length,\n receivingTransfers: receivingTransfers.length,\n totalTransfers: activeTransfers.length + receivingTransfers.length\n };\n }\n\n // Cancel file transfer\n cancelFileTransfer(fileId) {\n if (!this.fileTransferSystem) return false;\n return this.fileTransferSystem.cancelTransfer(fileId);\n }\n\n // Force cleanup of file transfer system\n cleanupFileTransferSystem() {\n if (this.fileTransferSystem) {\n console.log('\uD83E\uDDF9 Force cleaning up file transfer system...');\n this.fileTransferSystem.cleanup();\n this.fileTransferSystem = null;\n return true;\n }\n return false;\n }\n\n // Reinitialize file transfer system\n reinitializeFileTransfer() {\n try {\n console.log('\uD83D\uDD04 Reinitializing file transfer system...');\n if (this.fileTransferSystem) {\n this.fileTransferSystem.cleanup();\n }\n this.initializeFileTransfer();\n return true;\n } catch (error) {\n this._secureLog('error', '\u274C Failed to reinitialize file transfer system:', { errorType: error?.constructor?.name || 'Unknown' });\n return false;\n }\n }\n\n // Set file transfer callbacks\n setFileTransferCallbacks(onProgress, onReceived, onError) {\n this.onFileProgress = onProgress;\n this.onFileReceived = onReceived;\n this.onFileError = onError;\n \n console.log('\uD83D\uDD27 File transfer callbacks set:', {\n hasProgress: !!onProgress,\n hasReceived: !!onReceived,\n hasError: !!onError\n });\n \n // Reinitialize file transfer system if it exists to update callbacks\n if (this.fileTransferSystem) {\n console.log('\uD83D\uDD04 Reinitializing file transfer system with new callbacks...');\n this.initializeFileTransfer();\n }\n }\n\n // ============================================\n // SESSION ACTIVATION HANDLING\n // ============================================\n\n async handleSessionActivation(sessionData) {\n try {\n console.log('\uD83D\uDD10 Handling session activation:', sessionData);\n \n // Update session state\n this.currentSession = sessionData;\n this.sessionManager = sessionData.sessionManager;\n \n // FIX: More lenient checks for activation\n const hasKeys = !!(this.encryptionKey && this.macKey);\n const hasSession = !!(this.sessionManager && (this.sessionManager.hasActiveSession?.() || sessionData.sessionId));\n \n console.log('\uD83D\uDD0D Session activation status:', {\n hasKeys: hasKeys,\n hasSession: hasSession,\n sessionType: sessionData.sessionType,\n isDemo: sessionData.isDemo\n });\n \n // Force connection status if there is an active session\n if (hasSession) {\n console.log('\uD83D\uDD13 Session activated - forcing connection status to connected');\n this.onStatusChange('connected');\n \n console.log('\u26A0\uFE0F Session activated but NOT verified - cryptographic verification still required');\n }\n\n setTimeout(() => {\n try {\n this.initializeFileTransfer();\n } catch (error) {\n this._secureLog('warn', '\u26A0\uFE0F File transfer initialization failed during session activation:', { details: error.message });\n }\n }, 1000);\n \n console.log('\u2705 Session activation handled successfully');\n \n if (this.fileTransferSystem && this.isConnected()) {\n console.log('\uD83D\uDD04 Synchronizing file transfer keys after session activation...');\n \n if (typeof this.fileTransferSystem.onSessionUpdate === 'function') {\n this.fileTransferSystem.onSessionUpdate({\n keyFingerprint: this.keyFingerprint,\n sessionSalt: this.sessionSalt,\n hasMacKey: !!this.macKey\n });\n }\n }\n \n } catch (error) {\n this._secureLog('error', '\u274C Failed to handle session activation:', { errorType: error?.constructor?.name || 'Unknown' });\n }\n }\n // Method to check readiness of file transfers\ncheckFileTransferReadiness() {\n const status = {\n hasFileTransferSystem: !!this.fileTransferSystem,\n hasDataChannel: !!this.dataChannel,\n dataChannelState: this.dataChannel?.readyState,\n isConnected: this.isConnected(),\n isVerified: this.isVerified,\n hasEncryptionKey: !!this.encryptionKey,\n hasMacKey: !!this.macKey,\n ready: false\n };\n \n status.ready = status.hasFileTransferSystem && \n status.hasDataChannel && \n status.dataChannelState === 'open' && \n status.isConnected && \n status.isVerified;\n \n console.log('\uD83D\uDD0D File transfer readiness check:', status);\n return status;\n }\n\n // Method to force re-initialize file transfer system\n forceReinitializeFileTransfer() {\n try {\n console.log('\uD83D\uDD04 Force reinitializing file transfer system...');\n \n if (this.fileTransferSystem) {\n this.fileTransferSystem.cleanup();\n this.fileTransferSystem = null;\n }\n \n // Small delay before reinitialization\n setTimeout(() => {\n this.initializeFileTransfer();\n }, 500);\n \n return true;\n } catch (error) {\n this._secureLog('error', '\u274C Failed to force reinitialize file transfer:', { errorType: error?.constructor?.name || 'Unknown' });\n return false;\n }\n }\n\n // Method to get diagnostic information\n getFileTransferDiagnostics() {\n const diagnostics = {\n timestamp: new Date().toISOString(),\n webrtcManager: {\n hasDataChannel: !!this.dataChannel,\n dataChannelState: this.dataChannel?.readyState,\n isConnected: this.isConnected(),\n isVerified: this.isVerified,\n isInitiator: this.isInitiator,\n hasEncryptionKey: !!this.encryptionKey,\n hasMacKey: !!this.macKey,\n hasMetadataKey: !!this.metadataKey,\n hasKeyFingerprint: !!this.keyFingerprint,\n hasSessionSalt: !!this.sessionSalt\n },\n fileTransferSystem: null,\n globalState: {\n fileTransferActive: this._fileTransferActive || false,\n hasFileTransferSystem: !!this.fileTransferSystem,\n fileTransferSystemType: this.fileTransferSystem ? 'EnhancedSecureFileTransfer' : 'none'\n }\n };\n \n if (this.fileTransferSystem) {\n try {\n diagnostics.fileTransferSystem = this.fileTransferSystem.getSystemStatus();\n } catch (error) {\n diagnostics.fileTransferSystem = { error: error.message };\n }\n }\n \n return diagnostics;\n }\n\n getSupportedFileTypes() {\n if (!this.fileTransferSystem) {\n return { error: 'File transfer system not initialized' };\n }\n \n try {\n return this.fileTransferSystem.getSupportedFileTypes();\n } catch (error) {\n return { error: error.message };\n }\n }\n\n validateFile(file) {\n if (!this.fileTransferSystem) {\n return { \n isValid: false, \n errors: ['File transfer system not initialized'],\n fileType: null,\n fileSize: file?.size || 0,\n formattedSize: '0 B'\n };\n }\n \n try {\n return this.fileTransferSystem.validateFile(file);\n } catch (error) {\n return { \n isValid: false, \n errors: [error.message],\n fileType: null,\n fileSize: file?.size || 0,\n formattedSize: '0 B'\n };\n }\n }\n\n getFileTypeInfo() {\n if (!this.fileTransferSystem) {\n return { error: 'File transfer system not initialized' };\n }\n \n try {\n return this.fileTransferSystem.getFileTypeInfo();\n } catch (error) {\n return { error: error.message };\n }\n }\n\n async forceInitializeFileTransfer(options = {}) {\n const abortController = new AbortController();\n const { signal = abortController.signal, timeout = 6000 } = options;\n\n if (signal && signal !== abortController.signal) {\n signal.addEventListener('abort', () => abortController.abort());\n }\n try {\n if (!this.isVerified) {\n throw new Error('Connection not verified');\n }\n \n if (!this.dataChannel || this.dataChannel.readyState !== 'open') {\n throw new Error('Data channel not open');\n }\n \n if (!this.encryptionKey || !this.macKey) {\n throw new Error('Encryption keys not ready');\n }\n\n if (this.fileTransferSystem) {\n this.fileTransferSystem.cleanup();\n this.fileTransferSystem = null;\n }\n\n this.initializeFileTransfer();\n\n let attempts = 0;\n const maxAttempts = 50;\n const checkInterval = 100; \n const maxWaitTime = maxAttempts * checkInterval; \n\n const initializationPromise = new Promise((resolve, reject) => {\n const checkInitialization = () => {\n if (abortController.signal.aborted) {\n reject(new Error('Operation cancelled'));\n return;\n }\n \n if (this.fileTransferSystem) {\n resolve(true);\n return;\n }\n \n if (attempts >= maxAttempts) {\n reject(new Error(`Initialization timeout after ${maxWaitTime}ms`));\n return;\n }\n \n attempts++;\n setTimeout(checkInitialization, checkInterval);\n };\n \n checkInitialization();\n });\n\n await Promise.race([\n initializationPromise,\n new Promise((_, reject) => \n setTimeout(() => reject(new Error(`Global timeout after ${timeout}ms`)), timeout)\n )\n ]);\n \n if (this.fileTransferSystem) {\n return true;\n } else {\n throw new Error('Force initialization timeout');\n }\n \n } catch (error) {\n if (error.name === 'AbortError' || error.message.includes('cancelled')) {\n this._secureLog('info', '\u23F9\uFE0F File transfer initialization cancelled by user');\n return { cancelled: true };\n }\n \n this._secureLog('error', '\u274C Force file transfer initialization failed:', { \n errorType: error?.constructor?.name || 'Unknown',\n message: error.message,\n attempts: attempts\n });\n return { error: error.message, attempts: attempts };\n }\n }\n\n cancelFileTransferInitialization() {\n try {\n if (this.fileTransferSystem) {\n this.fileTransferSystem.cleanup();\n this.fileTransferSystem = null;\n this._fileTransferActive = false;\n this._secureLog('info', '\u23F9\uFE0F File transfer initialization cancelled');\n return true;\n }\n return false;\n } catch (error) {\n this._secureLog('error', '\u274C Failed to cancel file transfer initialization:', { \n errorType: error?.constructor?.name || 'Unknown' \n });\n return false;\n }\n }\n \n getFileTransferSystemStatus() {\n if (!this.fileTransferSystem) {\n return { available: false, status: 'not_initialized' };\n }\n \n try {\n const status = this.fileTransferSystem.getSystemStatus();\n return {\n available: true,\n status: status.status || 'unknown',\n activeTransfers: status.activeTransfers || 0,\n receivingTransfers: status.receivingTransfers || 0,\n systemType: 'EnhancedSecureFileTransfer'\n };\n } catch (error) {\n this._secureLog('error', '\u274C Failed to get file transfer system status:', { \n errorType: error?.constructor?.name || 'Unknown' \n });\n return { available: false, status: 'error', error: error.message };\n }\n }\n\n _validateNestedEncryptionSecurity() {\n if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey) {\n // Test secure IV generation with reuse prevention\n try {\n const testIV1 = this._generateSecureIV(EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE, 'securityTest1');\n const testIV2 = this._generateSecureIV(EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE, 'securityTest2');\n \n // Verify IVs are different and properly tracked\n if (testIV1.every((byte, index) => byte === testIV2[index])) {\n this._secureLog('error', '\u274C CRITICAL: Nested encryption security validation failed - IVs are identical!');\n return false;\n }\n \n // Verify IV tracking system is working\n const stats = this._getIVTrackingStats();\n if (stats.totalIVs < 2) {\n this._secureLog('error', '\u274C CRITICAL: IV tracking system not working properly');\n return false;\n }\n \n this._secureLog('info', '\u2705 Nested encryption security validation passed - secure IV generation working');\n return true;\n } catch (error) {\n this._secureLog('error', '\u274C CRITICAL: Nested encryption security validation failed:', {\n errorType: error.constructor.name,\n errorMessage: error.message\n });\n return false;\n }\n }\n return true;\n }\n}\n\nclass SecureKeyStorage {\n constructor() {\n // Use WeakMap for automatic garbage collection of unused keys\n this._keyStore = new WeakMap();\n this._keyMetadata = new Map(); // Metadata doesn't need WeakMap\n this._keyReferences = new Map(); // Strong references for active keys\n \n // Master encryption key for storage encryption\n this._storageMasterKey = null;\n this._initializeStorageMaster();\n\n setTimeout(() => {\n if (!this.validateStorageIntegrity()) {\n console.error('\u274C CRITICAL: Key storage integrity check failed');\n }\n }, 100);\n \n }\n\n async _initializeStorageMaster() {\n // Generate a master key for encrypting stored keys\n this._storageMasterKey = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n );\n }\n\n async storeKey(keyId, cryptoKey, metadata = {}) {\n if (!(cryptoKey instanceof CryptoKey)) {\n throw new Error('Only CryptoKey objects can be stored');\n }\n\n try {\n // For non-extractable keys, we can only store a reference\n if (!cryptoKey.extractable) {\n // Store the key reference directly without encryption\n this._keyReferences.set(keyId, cryptoKey);\n this._keyMetadata.set(keyId, {\n ...metadata,\n created: Date.now(),\n lastAccessed: Date.now(),\n extractable: false,\n encrypted: false // Mark as not encrypted\n });\n return true;\n }\n\n // For extractable keys, proceed with encryption\n const keyData = await crypto.subtle.exportKey('jwk', cryptoKey);\n const encryptedKeyData = await this._encryptKeyData(keyData);\n \n // Validate that extractable keys are properly encrypted\n if (!encryptedKeyData || encryptedKeyData.byteLength === 0) {\n throw new Error('Failed to encrypt extractable key data');\n }\n\n // Create a storage object\n const storageObject = {\n id: keyId,\n encryptedData: encryptedKeyData,\n algorithm: cryptoKey.algorithm,\n usages: cryptoKey.usages,\n extractable: cryptoKey.extractable,\n type: cryptoKey.type,\n timestamp: Date.now()\n };\n\n // Use WeakMap with the CryptoKey as the key\n this._keyStore.set(cryptoKey, storageObject);\n \n // Store reference for retrieval by ID\n this._keyReferences.set(keyId, cryptoKey);\n \n // Store metadata separately\n this._keyMetadata.set(keyId, {\n ...metadata,\n created: Date.now(),\n lastAccessed: Date.now(),\n extractable: true,\n encrypted: true // Mark extractable keys as encrypted\n });\n\n return true;\n } catch (error) {\n console.error('Failed to store key securely:', error);\n return false;\n }\n }\n\n async retrieveKey(keyId) {\n const metadata = this._keyMetadata.get(keyId);\n if (!metadata) {\n return null;\n }\n\n // Update access time\n metadata.lastAccessed = Date.now();\n\n // For non-encrypted keys (non-extractable), return directly\n if (!metadata.encrypted) {\n // Only non-extractable keys should be non-encrypted\n if (metadata.extractable === false) {\n return this._keyReferences.get(keyId);\n } else {\n // This should never happen - extractable keys must be encrypted\n this._secureLog('error', '\u274C SECURITY VIOLATION: Extractable key marked as non-encrypted', {\n keyId,\n extractable: metadata.extractable,\n encrypted: metadata.encrypted\n });\n return null;\n }\n }\n\n // For encrypted keys, decrypt and recreate\n try {\n const cryptoKey = this._keyReferences.get(keyId);\n const storedData = this._keyStore.get(cryptoKey);\n \n if (!storedData) {\n return null;\n }\n\n // Decrypt the key data\n const decryptedKeyData = await this._decryptKeyData(storedData.encryptedData);\n \n // Recreate the CryptoKey\n const recreatedKey = await crypto.subtle.importKey(\n 'jwk',\n decryptedKeyData,\n storedData.algorithm,\n storedData.extractable,\n storedData.usages\n );\n \n return recreatedKey;\n } catch (error) {\n console.error('Failed to retrieve key:', error);\n return null;\n }\n }\n\n async _encryptKeyData(keyData) {\n const dataToEncrypt = typeof keyData === 'object' \n ? JSON.stringify(keyData) \n : keyData;\n \n const encoder = new TextEncoder();\n const data = encoder.encode(dataToEncrypt);\n \n const iv = crypto.getRandomValues(new Uint8Array(12));\n \n const encryptedData = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n this._storageMasterKey,\n data\n );\n\n // Return IV + encrypted data\n const result = new Uint8Array(iv.length + encryptedData.byteLength);\n result.set(iv, 0);\n result.set(new Uint8Array(encryptedData), iv.length);\n \n return result;\n }\n\n async _decryptKeyData(encryptedData) {\n const iv = encryptedData.slice(0, 12);\n const data = encryptedData.slice(12);\n \n const decryptedData = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv },\n this._storageMasterKey,\n data\n );\n\n const decoder = new TextDecoder();\n const jsonString = decoder.decode(decryptedData);\n \n try {\n return JSON.parse(jsonString);\n } catch {\n return decryptedData;\n }\n }\n\n secureWipe(keyId) {\n const cryptoKey = this._keyReferences.get(keyId);\n \n if (cryptoKey) {\n // Remove from WeakMap (will be GC'd)\n this._keyStore.delete(cryptoKey);\n // Remove strong reference\n this._keyReferences.delete(keyId);\n // Remove metadata\n this._keyMetadata.delete(keyId);\n }\n\n // Overwrite memory locations if possible\n if (typeof window.gc === 'function') {\n window.gc();\n }\n }\n\n secureWipeAll() {\n // Clear all references\n this._keyReferences.clear();\n this._keyMetadata.clear();\n \n // WeakMap entries will be garbage collected\n this._keyStore = new WeakMap();\n \n // Force garbage collection if available\n if (typeof window.gc === 'function') {\n window.gc();\n }\n }\n\n // Validate storage integrity\n validateStorageIntegrity() {\n const violations = [];\n \n for (const [keyId, metadata] of this._keyMetadata.entries()) {\n // Check: extractable keys must be encrypted\n if (metadata.extractable === true && metadata.encrypted !== true) {\n violations.push({\n keyId,\n type: 'EXTRACTABLE_KEY_NOT_ENCRYPTED',\n metadata\n });\n }\n \n // Check: non-extractable keys should not be encrypted\n if (metadata.extractable === false && metadata.encrypted === true) {\n violations.push({\n keyId,\n type: 'NON_EXTRACTABLE_KEY_ENCRYPTED',\n metadata\n });\n }\n }\n \n if (violations.length > 0) {\n console.error('\u274C Storage integrity violations detected:', violations);\n return false;\n }\n \n return true;\n }\n\n getStorageStats() {\n return {\n totalKeys: this._keyReferences.size,\n metadata: Array.from(this._keyMetadata.entries()).map(([id, meta]) => ({\n id,\n created: meta.created,\n lastAccessed: meta.lastAccessed,\n age: Date.now() - meta.created\n }))\n };\n }\n\n // Method _generateNextSequenceNumber moved to constructor area for early availability\n\n /**\n * Validate incoming message sequence number\n * This prevents replay attacks and ensures message ordering\n */\n _validateIncomingSequenceNumber(receivedSeq, context = 'unknown') {\n try {\n if (!this.replayProtectionEnabled) {\n return true; // Skip validation if disabled\n }\n\n // Check if sequence number is within acceptable range\n if (receivedSeq < this.expectedSequenceNumber - this.replayWindowSize) {\n this._secureLog('warn', '\u26A0\uFE0F Sequence number too old - possible replay attack', {\n received: receivedSeq,\n expected: this.expectedSequenceNumber,\n context: context,\n timestamp: Date.now()\n });\n return false;\n }\n\n // Check if sequence number is too far ahead (DoS protection)\n if (receivedSeq > this.expectedSequenceNumber + this.maxSequenceGap) {\n this._secureLog('warn', '\u26A0\uFE0F Sequence number gap too large - possible DoS attack', {\n received: receivedSeq,\n expected: this.expectedSequenceNumber,\n gap: receivedSeq - this.expectedSequenceNumber,\n context: context,\n timestamp: Date.now()\n });\n return false;\n }\n\n // Check if sequence number is already in replay window\n if (this.replayWindow.has(receivedSeq)) {\n this._secureLog('warn', '\u26A0\uFE0F Duplicate sequence number detected - replay attack', {\n received: receivedSeq,\n context: context,\n timestamp: Date.now()\n });\n return false;\n }\n\n // Add to replay window\n this.replayWindow.add(receivedSeq);\n \n // Maintain sliding window size\n if (this.replayWindow.size > this.replayWindowSize) {\n const oldestSeq = Math.min(...this.replayWindow);\n this.replayWindow.delete(oldestSeq);\n }\n\n // Update expected sequence number if this is the next expected\n if (receivedSeq === this.expectedSequenceNumber) {\n this.expectedSequenceNumber++;\n \n // Clean up replay window entries that are no longer needed\n while (this.replayWindow.has(this.expectedSequenceNumber - this.replayWindowSize - 1)) {\n this.replayWindow.delete(this.expectedSequenceNumber - this.replayWindowSize - 1);\n }\n }\n\n this._secureLog('debug', '\u2705 Sequence number validation successful', {\n received: receivedSeq,\n expected: this.expectedSequenceNumber,\n context: context,\n timestamp: Date.now()\n });\n\n return true;\n } catch (error) {\n this._secureLog('error', '\u274C Sequence number validation failed', {\n error: error.message,\n context: context,\n timestamp: Date.now()\n });\n return false;\n }\n }\n\n // Method _createMessageAAD moved to constructor area for early availability\n\n /**\n * Validate message AAD with sequence number\n * This ensures message integrity and prevents replay attacks\n */\n _validateMessageAAD(aadString, expectedMessageType = null) {\n try {\n const aad = JSON.parse(aadString);\n \n // Validate session binding\n if (aad.sessionId !== (this.currentSession?.sessionId || 'unknown')) {\n throw new Error('AAD sessionId mismatch - possible replay attack');\n }\n \n if (aad.keyFingerprint !== (this.keyFingerprint || 'unknown')) {\n throw new Error('AAD keyFingerprint mismatch - possible key substitution attack');\n }\n \n // Validate sequence number\n if (!this._validateIncomingSequenceNumber(aad.sequenceNumber, aad.messageType)) {\n throw new Error('Sequence number validation failed - possible replay or DoS attack');\n }\n \n // Validate message type if specified\n if (expectedMessageType && aad.messageType !== expectedMessageType) {\n throw new Error(`AAD messageType mismatch - expected ${expectedMessageType}, got ${aad.messageType}`);\n }\n \n return aad;\n } catch (error) {\n this._secureLog('error', 'AAD validation failed', { error: error.message, aadString });\n throw new Error(`AAD validation failed: ${error.message}`);\n }\n }\n\n /**\n * Get anti-replay protection status\n * This shows the current state of replay protection\n */\n getAntiReplayStatus() {\n const status = {\n replayProtectionEnabled: this.replayProtectionEnabled,\n replayWindowSize: this.replayWindowSize,\n currentReplayWindowSize: this.replayWindow.size,\n sequenceNumber: this.sequenceNumber,\n expectedSequenceNumber: this.expectedSequenceNumber,\n maxSequenceGap: this.maxSequenceGap,\n replayWindowEntries: Array.from(this.replayWindow).sort((a, b) => a - b)\n };\n\n this._secureLog('info', 'Anti-replay status retrieved', status);\n return status;\n }\n\n /**\n * Configure anti-replay protection\n * This allows fine-tuning of replay protection parameters\n */\n configureAntiReplayProtection(config) {\n try {\n if (config.windowSize !== undefined) {\n if (config.windowSize < 16 || config.windowSize > 1024) {\n throw new Error('Replay window size must be between 16 and 1024');\n }\n this.replayWindowSize = config.windowSize;\n }\n\n if (config.maxGap !== undefined) {\n if (config.maxGap < 10 || config.maxGap > 1000) {\n throw new Error('Max sequence gap must be between 10 and 1000');\n }\n this.maxSequenceGap = config.maxGap;\n }\n\n if (config.enabled !== undefined) {\n this.replayProtectionEnabled = config.enabled;\n }\n\n this._secureLog('info', 'Anti-replay protection configured', config);\n return true;\n } catch (error) {\n this._secureLog('error', 'Failed to configure anti-replay protection', { error: error.message });\n return false;\n }\n }\n\n\n}\n\nexport { EnhancedSecureWebRTCManager };", "class PayPerSessionManager {\n constructor(config = {}) {\n this.sessionPrices = {\n demo: { sats: 0, hours: 0.1, usd: 0.00, securityLevel: 'basic' }, \n basic: { sats: 5000, hours: 1, usd: 2.00, securityLevel: 'enhanced' },\n premium: { sats: 20000, hours: 6, usd: 8.00, securityLevel: 'maximum' }\n };\n \n this.currentSession = null;\n this.sessionTimer = null;\n this.onSessionExpired = null;\n this.staticLightningAddress = \"dullpastry62@walletofsatoshi.com\";\n \n // Storage of used preimage to prevent reuse\n this.usedPreimages = new Set();\n this.preimageCleanupInterval = null;\n \n // FIXED DEMO mode: Stricter control\n this.demoSessions = new Map(); \n this.maxDemoSessionsPerUser = 3; \n this.demoCooldownPeriod = 24 * 60 * 60 * 1000; \n this.demoSessionCooldown = 1 * 60 * 1000; \n this.demoSessionMaxDuration = 6 * 60 * 1000; \n \n // NEW: Global tracking of active demo sessions\n this.activeDemoSessions = new Set(); \n this.maxGlobalDemoSessions = 10; \n \n // NEW: Tracking of terminated sessions to prevent rapid reconnection\n this.completedDemoSessions = new Map(); \n this.minTimeBetweenCompletedSessions = 15 * 60 * 1000; \n\n // Minimum cost for paid sessions (protection against micropayment attacks)\n this.minimumPaymentSats = 1000;\n \n this.verificationConfig = {\n method: config.method || 'lnbits',\n apiUrl: config.apiUrl || 'https://demo.lnbits.com',\n apiKey: config.apiKey || 'a7226682253f4dd7bdb2d9487a9a59f8', \n walletId: config.walletId || '649903697b03457d8b12c4eae7b2fab9',\n isDemo: config.isDemo !== undefined ? config.isDemo : true,\n demoTimeout: 30000, \n retryAttempts: 3,\n invoiceExpiryMinutes: 15\n };\n \n // Rate limiting for API requests\n this.lastApiCall = 0;\n this.apiCallMinInterval = 1000; \n \n // Run periodic tasks\n this.startPreimageCleanup();\n this.startDemoSessionCleanup();\n this.startActiveDemoSessionCleanup();\n \n this.globalDemoCounter = 0;\n this.memoryStorage = new Map();\n this.currentTabId = null;\n this.tabHeartbeatInterval = null;\n this.initializePersistentStorage();\n this.performEnhancedCleanup();\n const multiTabCheck = this.checkMultiTabProtection();\n if (!multiTabCheck.allowed) {\n console.warn('\u274C Multi-tab protection triggered:', multiTabCheck.message);\n }\n \n console.log('\uD83D\uDCB0 PayPerSessionManager initialized with TIERED security levels');\n \n setInterval(() => {\n this.savePersistentData();\n }, 30000);\n this.notifySecurityUpdate = () => {\n document.dispatchEvent(new CustomEvent('security-level-updated', {\n detail: { timestamp: Date.now(), manager: 'webrtc' }\n }));\n };\n console.log('\uD83D\uDCB0 PayPerSessionManager initialized with ENHANCED secure demo mode and auto-save');\n }\n\n getSecurityLevelForSession(sessionType) {\n const pricing = this.sessionPrices[sessionType];\n if (!pricing) return 'basic';\n \n return pricing.securityLevel || 'basic';\n }\n\n // Check if the function is allowed for the given session type\n isFeatureAllowedForSession(sessionType, feature) {\n const securityLevel = this.getSecurityLevelForSession(sessionType);\n \n const featureMatrix = {\n 'basic': {\n // DEMO \u0441\u0435\u0441\u0441\u0438\u0438 - \u0442\u043E\u043B\u044C\u043A\u043E \u0431\u0430\u0437\u043E\u0432\u044B\u0435 \u0444\u0443\u043D\u043A\u0446\u0438\u0438\n hasEncryption: true,\n hasECDH: true,\n hasECDSA: false,\n hasMutualAuth: false,\n hasMetadataProtection: false,\n hasEnhancedReplayProtection: false,\n hasNonExtractableKeys: false,\n hasRateLimiting: true,\n hasEnhancedValidation: false,\n hasPFS: false,\n \n // Advanced features are DISABLED for demo\n hasNestedEncryption: false,\n hasPacketPadding: false,\n hasPacketReordering: false,\n hasAntiFingerprinting: false,\n hasFakeTraffic: false,\n hasDecoyChannels: false,\n hasMessageChunking: false\n },\n 'enhanced': {\n // BASIC paid sessions - improved security\n hasEncryption: true,\n hasECDH: true,\n hasECDSA: true,\n hasMutualAuth: true,\n hasMetadataProtection: true,\n hasEnhancedReplayProtection: true,\n hasNonExtractableKeys: true,\n hasRateLimiting: true,\n hasEnhancedValidation: true,\n hasPFS: true,\n \n // Partially enabled advanced features\n hasNestedEncryption: true,\n hasPacketPadding: true,\n hasPacketReordering: false, \n hasAntiFingerprinting: false,\n hasFakeTraffic: false, \n hasDecoyChannels: false,\n hasMessageChunking: false\n },\n 'maximum': {\n // PREMIUM sessions - all functions included\n hasEncryption: true,\n hasECDH: true,\n hasECDSA: true,\n hasMutualAuth: true,\n hasMetadataProtection: true,\n hasEnhancedReplayProtection: true,\n hasNonExtractableKeys: true,\n hasRateLimiting: true,\n hasEnhancedValidation: true,\n hasPFS: true,\n \n // ALL advanced features\n hasNestedEncryption: true,\n hasPacketPadding: true,\n hasPacketReordering: true,\n hasAntiFingerprinting: true,\n hasFakeTraffic: true,\n hasDecoyChannels: true,\n hasMessageChunking: true\n }\n };\n\n return featureMatrix[securityLevel]?.[feature] || false;\n }\n\n // ============================================\n // FIXED DEMO MODE: Improved controls and management\n // ============================================\n\n startActiveDemoSessionCleanup() {\n setInterval(() => {\n const now = Date.now();\n let cleanedCount = 0;\n \n for (const preimage of this.activeDemoSessions) {\n const demoTimestamp = this.extractDemoTimestamp(preimage);\n if (demoTimestamp && (now - demoTimestamp) > this.demoSessionMaxDuration) {\n this.activeDemoSessions.delete(preimage);\n cleanedCount++;\n }\n }\n \n if (cleanedCount > 0) {\n console.log(`\uD83E\uDDF9 Cleaned ${cleanedCount} expired active demo sessions`);\n }\n }, 30000); \n }\n \n\n startDemoSessionCleanup() {\n setInterval(() => {\n const now = Date.now();\n const maxAge = 25 * 60 * 60 * 1000; \n \n let cleanedCount = 0;\n for (const [identifier, data] of this.demoSessions.entries()) {\n if (now - data.lastUsed > maxAge) {\n this.demoSessions.delete(identifier);\n cleanedCount++;\n }\n \n if (data.sessions) {\n const originalCount = data.sessions.length;\n data.sessions = data.sessions.filter(session => \n now - session.timestamp < maxAge\n );\n \n if (data.sessions.length === 0 && now - data.lastUsed > maxAge) {\n this.demoSessions.delete(identifier);\n cleanedCount++;\n }\n }\n }\n \n for (const [identifier, sessions] of this.completedDemoSessions.entries()) {\n const filteredSessions = sessions.filter(session => \n now - session.endTime < maxAge\n );\n \n if (filteredSessions.length === 0) {\n this.completedDemoSessions.delete(identifier);\n } else {\n this.completedDemoSessions.set(identifier, filteredSessions);\n }\n }\n \n if (cleanedCount > 0) {\n console.log(`\uD83E\uDDF9 Cleaned ${cleanedCount} old demo session records`);\n }\n }, 60 * 60 * 1000); \n }\n\n // IMPROVED user fingerprint generation\n generateAdvancedUserFingerprint() {\n try {\n const basicComponents = [\n navigator.userAgent || '',\n navigator.language || '',\n screen.width + 'x' + screen.height,\n Intl.DateTimeFormat().resolvedOptions().timeZone || '',\n navigator.hardwareConcurrency || 0,\n navigator.deviceMemory || 0,\n navigator.platform || '',\n navigator.cookieEnabled ? '1' : '0',\n window.screen.colorDepth || 0,\n window.screen.pixelDepth || 0,\n navigator.maxTouchPoints || 0,\n navigator.onLine ? '1' : '0'\n ];\n\n const hardwareComponents = [];\n \n // WebGL fingerprint \n try {\n const canvas = document.createElement('canvas');\n const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n if (gl) {\n const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');\n if (debugInfo) {\n hardwareComponents.push(gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || '');\n hardwareComponents.push(gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || '');\n }\n hardwareComponents.push(gl.getParameter(gl.VERSION) || '');\n hardwareComponents.push(gl.getParameter(gl.SHADING_LANGUAGE_VERSION) || '');\n }\n } catch (e) {\n hardwareComponents.push('webgl_error');\n }\n\n // Canvas print \n try {\n const canvas = document.createElement('canvas');\n canvas.width = 200;\n canvas.height = 50;\n const ctx = canvas.getContext('2d');\n ctx.textBaseline = 'top';\n ctx.font = '14px Arial';\n ctx.fillText('SecureBit Demo Fingerprint \uD83D\uDD12', 2, 2);\n ctx.fillStyle = 'rgba(255,0,0,0.5)';\n ctx.fillRect(50, 10, 20, 20);\n hardwareComponents.push(canvas.toDataURL());\n } catch (e) {\n hardwareComponents.push('canvas_error');\n }\n\n // Audio fingerprint \n try {\n const audioContext = new (window.AudioContext || window.webkitAudioContext)();\n const oscillator = audioContext.createOscillator();\n const analyser = audioContext.createAnalyser();\n const gain = audioContext.createGain();\n \n oscillator.connect(analyser);\n analyser.connect(gain);\n gain.connect(audioContext.destination);\n \n oscillator.frequency.setValueAtTime(1000, audioContext.currentTime);\n gain.gain.setValueAtTime(0, audioContext.currentTime);\n \n hardwareComponents.push(audioContext.sampleRate.toString());\n hardwareComponents.push(audioContext.state);\n hardwareComponents.push(analyser.frequencyBinCount.toString());\n \n audioContext.close();\n } catch (e) {\n hardwareComponents.push('audio_error');\n }\n\n // CPU Performance \n const cpuBenchmark = this.performCPUBenchmark();\n hardwareComponents.push(cpuBenchmark);\n\n const allComponents = [...basicComponents, ...hardwareComponents];\n\n let primaryHash = 0;\n let secondaryHash = 0;\n let tertiaryHash = 0;\n \n const primaryStr = allComponents.slice(0, 8).join('|');\n const secondaryStr = allComponents.slice(8, 16).join('|');\n const tertiaryStr = allComponents.slice(16).join('|');\n \n for (let i = 0; i < primaryStr.length; i++) {\n const char = primaryStr.charCodeAt(i);\n primaryHash = ((primaryHash << 7) - primaryHash) + char;\n primaryHash = primaryHash & primaryHash;\n }\n\n for (let i = 0; i < secondaryStr.length; i++) {\n const char = secondaryStr.charCodeAt(i);\n secondaryHash = ((secondaryHash << 11) - secondaryHash) + char;\n secondaryHash = secondaryHash & secondaryHash;\n }\n \n for (let i = 0; i < tertiaryStr.length; i++) {\n const char = tertiaryStr.charCodeAt(i);\n tertiaryHash = ((tertiaryHash << 13) - tertiaryHash) + char;\n tertiaryHash = tertiaryHash & tertiaryHash;\n }\n \n const combined = `${Math.abs(primaryHash).toString(36)}_${Math.abs(secondaryHash).toString(36)}_${Math.abs(tertiaryHash).toString(36)}`;\n \n console.log('\uD83D\uDD12 Enhanced fingerprint generated:', {\n components: allComponents.length,\n primaryLength: primaryStr.length,\n secondaryLength: secondaryStr.length,\n tertiaryLength: tertiaryStr.length,\n fingerprintLength: combined.length\n });\n \n return combined;\n \n } catch (error) {\n console.warn('Failed to generate enhanced fingerprint:', error);\n return 'fallback_' + Date.now().toString(36) + '_' + Math.random().toString(36).substr(2, 9);\n }\n }\n\n performCPUBenchmark() {\n const start = performance.now();\n let result = 0;\n \n for (let i = 0; i < 100000; i++) {\n result += Math.sin(i) * Math.cos(i);\n }\n \n const end = performance.now();\n const duration = Math.round(end - start);\n \n if (duration < 5) return 'fast_cpu';\n if (duration < 15) return 'medium_cpu';\n if (duration < 30) return 'slow_cpu';\n return 'very_slow_cpu';\n }\n\n initializePersistentStorage() {\n this.storageKeys = {\n demoSessions: 'sb_demo_sessions_v2',\n completedSessions: 'sb_completed_sessions_v2',\n globalCounter: 'sb_global_demo_counter_v2',\n lastCleanup: 'sb_last_cleanup_v2',\n hardwareFingerprint: 'sb_hw_fingerprint_v2'\n };\n \n this.loadPersistentData();\n }\n\n loadPersistentData() {\n try {\n const savedDemoSessions = this.getFromStorage(this.storageKeys.demoSessions);\n if (savedDemoSessions) {\n const parsed = JSON.parse(savedDemoSessions);\n for (const [key, value] of Object.entries(parsed)) {\n this.demoSessions.set(key, value);\n }\n }\n \n const savedCompletedSessions = this.getFromStorage(this.storageKeys.completedSessions);\n if (savedCompletedSessions) {\n const parsed = JSON.parse(savedCompletedSessions);\n for (const [key, value] of Object.entries(parsed)) {\n this.completedDemoSessions.set(key, value);\n }\n }\n \n const savedGlobalCounter = this.getFromStorage(this.storageKeys.globalCounter);\n if (savedGlobalCounter) {\n this.globalDemoCounter = parseInt(savedGlobalCounter) || 0;\n } else {\n this.globalDemoCounter = 0;\n }\n \n console.log('\uD83D\uDCCA Persistent data loaded:', {\n demoSessions: this.demoSessions.size,\n completedSessions: this.completedDemoSessions.size,\n globalCounter: this.globalDemoCounter\n });\n \n } catch (error) {\n console.warn('Failed to load persistent data:', error);\n this.globalDemoCounter = 0;\n }\n }\n\n savePersistentData() {\n try {\n const demoSessionsObj = Object.fromEntries(this.demoSessions);\n this.setToStorage(this.storageKeys.demoSessions, JSON.stringify(demoSessionsObj));\n \n const completedSessionsObj = Object.fromEntries(this.completedDemoSessions);\n this.setToStorage(this.storageKeys.completedSessions, JSON.stringify(completedSessionsObj));\n \n this.setToStorage(this.storageKeys.globalCounter, this.globalDemoCounter.toString());\n \n this.setToStorage(this.storageKeys.lastCleanup, Date.now().toString());\n \n } catch (error) {\n console.warn('Failed to save persistent data:', error);\n }\n }\n\n getFromStorage(key) {\n try {\n if (typeof localStorage !== 'undefined') {\n const value = localStorage.getItem(key);\n if (value) return value;\n }\n } catch (e) {}\n \n try {\n if (typeof sessionStorage !== 'undefined') {\n const value = sessionStorage.getItem(key);\n if (value) return value;\n }\n } catch (e) {}\n \n try {\n if ('caches' in window) {\n }\n } catch (e) {}\n \n return null;\n }\n\n setToStorage(key, value) {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(key, value);\n }\n } catch (e) {}\n \n try {\n if (typeof sessionStorage !== 'undefined') {\n sessionStorage.setItem(key, value);\n }\n } catch (e) {}\n \n if (!this.memoryStorage) this.memoryStorage = new Map();\n this.memoryStorage.set(key, value);\n }\n\n checkAntiResetProtection(userFingerprint) {\n if (!this.globalDemoCounter) {\n this.globalDemoCounter = 0;\n }\n \n const hardwareFingerprint = this.getHardwareFingerprint();\n \n const savedHardwareFingerprint = this.getFromStorage(this.storageKeys.hardwareFingerprint);\n \n if (savedHardwareFingerprint && savedHardwareFingerprint !== hardwareFingerprint) {\n console.warn('\uD83D\uDEA8 Hardware fingerprint mismatch detected - possible reset attempt');\n \n this.globalDemoCounter += 5;\n this.savePersistentData();\n \n return {\n isValid: false,\n reason: 'hardware_mismatch',\n penalty: 5\n };\n }\n \n this.setToStorage(this.storageKeys.hardwareFingerprint, hardwareFingerprint);\n \n if (this.globalDemoCounter >= 10) {\n return {\n isValid: false,\n reason: 'global_limit_exceeded',\n globalCount: this.globalDemoCounter\n };\n }\n \n return {\n isValid: true,\n globalCount: this.globalDemoCounter\n };\n }\n\n getHardwareFingerprint() {\n const components = [];\n\n components.push(navigator.hardwareConcurrency || 0);\n components.push(navigator.deviceMemory || 0);\n \n try {\n const canvas = document.createElement('canvas');\n const gl = canvas.getContext('webgl');\n if (gl) {\n const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');\n if (debugInfo) {\n components.push(gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || '');\n components.push(gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || '');\n }\n }\n } catch (e) {\n components.push('webgl_unavailable');\n }\n \n components.push(screen.width);\n components.push(screen.height);\n components.push(screen.colorDepth);\n\n components.push(Intl.DateTimeFormat().resolvedOptions().timeZone);\n \n let hash = 0;\n const str = components.join('|');\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash;\n }\n \n return Math.abs(hash).toString(36);\n }\n\n registerEnhancedDemoSessionUsage(userFingerprint, preimage) {\n const session = this.registerDemoSessionUsage(userFingerprint, preimage);\n \n this.savePersistentData();\n\n console.log('\uD83D\uDCCA Enhanced demo session registered:', {\n userFingerprint: userFingerprint.substring(0, 12),\n globalCount: this.globalDemoCounter,\n sessionId: session.sessionId,\n timestamp: new Date().toISOString()\n });\n \n return session;\n }\n\n // COMPLETELY REWRITTEN demo session limits check\n checkEnhancedDemoSessionLimits(userFingerprint) {\n const antiResetCheck = this.checkAntiResetProtection(userFingerprint);\n if (!antiResetCheck.isValid) {\n return {\n allowed: false,\n reason: antiResetCheck.reason,\n message: this.getAntiResetMessage(antiResetCheck),\n globalCount: antiResetCheck.globalCount,\n penalty: antiResetCheck.penalty\n };\n }\n \n const regularCheck = this.checkDemoSessionLimits(userFingerprint);\n \n if (regularCheck.allowed) {\n this.globalDemoCounter++;\n this.savePersistentData();\n }\n \n return {\n ...regularCheck,\n globalCount: this.globalDemoCounter\n };\n }\n\n\n\n getAntiResetMessage(antiResetCheck) {\n switch (antiResetCheck.reason) {\n case 'hardware_mismatch':\n return 'An attempt to reset restrictions was detected. Access to demo mode is temporarily restricted.';\n case 'global_limit_exceeded':\n return `Global demo session limit exceeded (${antiResetCheck.globalCount}/10). A paid session is required to continue.`;\n default:\n return 'Access to demo mode is restricted for security reasons.';\n }\n }\n\n\n\n // FIXED demo session usage registration\n registerDemoSessionUsage(userFingerprint, preimage) {\n const now = Date.now();\n const userData = this.demoSessions.get(userFingerprint) || {\n count: 0,\n lastUsed: 0,\n sessions: [],\n firstUsed: now\n };\n \n userData.count++;\n userData.lastUsed = now;\n \n // Add a new session with preimage for tracking\n const newSession = {\n timestamp: now,\n sessionId: crypto.getRandomValues(new Uint32Array(1))[0].toString(36),\n duration: this.demoSessionMaxDuration,\n preimage: preimage, \n status: 'active'\n };\n \n userData.sessions.push(newSession);\n \n // Clear old sessions (only those older than 24 hours)\n userData.sessions = userData.sessions.filter(session => \n now - session.timestamp < this.demoCooldownPeriod\n );\n \n // NEW: Add to global set of active sessions\n this.activeDemoSessions.add(preimage);\n \n this.demoSessions.set(userFingerprint, userData);\n \n console.log(`\uD83D\uDCCA Demo session registered for user ${userFingerprint.substring(0, 12)} (${userData.sessions.length}/${this.maxDemoSessionsPerUser} today)`);\n console.log(`\uD83C\uDF10 Global active demo sessions: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`);\n \n return newSession;\n }\n\n performEnhancedCleanup() {\n const now = Date.now();\n const lastCleanup = parseInt(this.getFromStorage(this.storageKeys.lastCleanup)) || 0;\n \n if (now - lastCleanup < 6 * 60 * 60 * 1000) {\n return;\n }\n \n console.log('\uD83E\uDDF9 Performing enhanced cleanup...');\n \n const maxAge = 25 * 60 * 60 * 1000;\n let cleanedSessions = 0;\n \n for (const [identifier, data] of this.demoSessions.entries()) {\n if (now - data.lastUsed > maxAge) {\n this.demoSessions.delete(identifier);\n cleanedSessions++;\n }\n }\n \n let cleanedCompleted = 0;\n for (const [identifier, sessions] of this.completedDemoSessions.entries()) {\n const filteredSessions = sessions.filter(session => \n now - session.endTime < maxAge\n );\n \n if (filteredSessions.length === 0) {\n this.completedDemoSessions.delete(identifier);\n cleanedCompleted++;\n } else {\n this.completedDemoSessions.set(identifier, filteredSessions);\n }\n }\n \n const weekAgo = 7 * 24 * 60 * 60 * 1000;\n if (now - lastCleanup > weekAgo) {\n this.globalDemoCounter = Math.max(0, this.globalDemoCounter - 3);\n console.log('\uD83D\uDD04 Global demo counter reset (weekly):', this.globalDemoCounter);\n }\n \n this.savePersistentData();\n \n console.log('\u2705 Enhanced cleanup completed:', {\n cleanedSessions,\n cleanedCompleted,\n globalCounter: this.globalDemoCounter\n });\n }\n\n checkMultiTabProtection() {\n const tabId = 'tab_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);\n const activeTabsKey = 'sb_active_tabs';\n \n try {\n const activeTabsStr = this.getFromStorage(activeTabsKey);\n const activeTabs = activeTabsStr ? JSON.parse(activeTabsStr) : [];\n \n const now = Date.now();\n const validTabs = activeTabs.filter(tab => now - tab.timestamp < 30000);\n \n if (validTabs.length >= 2) {\n return {\n allowed: false,\n reason: 'multiple_tabs',\n message: 'Demo mode is only available in one tab at a time..'\n };\n }\n\n validTabs.push({\n tabId: tabId,\n timestamp: now\n });\n \n this.setToStorage(activeTabsKey, JSON.stringify(validTabs));\n this.currentTabId = tabId;\n\n this.startTabHeartbeat();\n \n return {\n allowed: true,\n tabId: tabId\n };\n \n } catch (error) {\n console.warn('Multi-tab protection error:', error);\n return { allowed: true }; \n }\n }\n\n startTabHeartbeat() {\n if (this.tabHeartbeatInterval) {\n clearInterval(this.tabHeartbeatInterval);\n }\n \n this.tabHeartbeatInterval = setInterval(() => {\n this.updateTabHeartbeat();\n }, 10000); \n }\n\n updateTabHeartbeat() {\n if (!this.currentTabId) return;\n \n try {\n const activeTabsKey = 'sb_active_tabs';\n const activeTabsStr = this.getFromStorage(activeTabsKey);\n const activeTabs = activeTabsStr ? JSON.parse(activeTabsStr) : [];\n \n const updatedTabs = activeTabs.map(tab => {\n if (tab.tabId === this.currentTabId) {\n return {\n ...tab,\n timestamp: Date.now()\n };\n }\n return tab;\n });\n \n this.setToStorage(activeTabsKey, JSON.stringify(updatedTabs));\n \n } catch (error) {\n console.warn('Tab heartbeat update failed:', error);\n }\n }\n\n // NEW method: Register demo session completion\n registerDemoSessionCompletion(userFingerprint, sessionDuration, preimage) {\n const now = Date.now();\n \n // Remove from active sessions\n if (preimage) {\n this.activeDemoSessions.delete(preimage);\n }\n \n // Add to completed sessions\n const completedSessions = this.completedDemoSessions.get(userFingerprint) || [];\n completedSessions.push({\n endTime: now,\n duration: sessionDuration,\n preimage: preimage ? preimage.substring(0, 16) + '...' : 'unknown' // \u041B\u043E\u0433\u0438\u0440\u0443\u0435\u043C \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0430\u0441\u0442\u044C \u0434\u043B\u044F \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0441\u0442\u0438\n });\n \n // Store only the last completed sessions\n const filteredSessions = completedSessions\n .filter(session => now - session.endTime < this.minTimeBetweenCompletedSessions)\n .slice(-5); \n \n this.completedDemoSessions.set(userFingerprint, filteredSessions);\n \n // Update the status in the user's master data\n const userData = this.demoSessions.get(userFingerprint);\n if (userData && userData.sessions) {\n const session = userData.sessions.find(s => s.preimage === preimage);\n if (session) {\n session.status = 'completed';\n session.endTime = now;\n }\n }\n \n console.log(`\u2705 Demo session completed for user ${userFingerprint.substring(0, 12)}`);\n console.log(`\uD83C\uDF10 Global active demo sessions: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`);\n }\n\n // ENHANCED demo preimage generation with additional protection\n generateSecureDemoPreimage() {\n try {\n const timestamp = Date.now();\n const randomBytes = crypto.getRandomValues(new Uint8Array(24));\n const timestampBytes = new Uint8Array(4);\n const versionBytes = new Uint8Array(4);\n \n // Pack the timestamp\n const timestampSeconds = Math.floor(timestamp / 1000);\n timestampBytes[0] = (timestampSeconds >>> 24) & 0xFF;\n timestampBytes[1] = (timestampSeconds >>> 16) & 0xFF;\n timestampBytes[2] = (timestampSeconds >>> 8) & 0xFF;\n timestampBytes[3] = timestampSeconds & 0xFF;\n \n // IMPROVED version marker with additional protection\n versionBytes[0] = 0xDE; \n versionBytes[1] = 0xE0; \n versionBytes[2] = 0x00; \n versionBytes[3] = 0x02; \n \n const combined = new Uint8Array(32);\n combined.set(versionBytes, 0);\n combined.set(timestampBytes, 4);\n combined.set(randomBytes, 8);\n \n const preimage = Array.from(combined).map(b => b.toString(16).padStart(2, '0')).join('');\n \n console.log(`\uD83C\uDFAE Generated SECURE demo preimage v2: ${preimage.substring(0, 16)}...`);\n return preimage;\n \n } catch (error) {\n console.error('Failed to generate demo preimage:', error);\n throw new Error('Failed to generate secure demo preimage');\n }\n }\n\n // UPDATED demo preimage check\n isDemoPreimage(preimage) {\n if (!preimage || typeof preimage !== 'string' || preimage.length !== 64) {\n return false;\n }\n \n // Check the demo marker (support versions 1 and 2)\n const lower = preimage.toLowerCase();\n return lower.startsWith('dee00001') || lower.startsWith('dee00002');\n }\n\n // Extract timestamp from demo preimage\n extractDemoTimestamp(preimage) {\n if (!this.isDemoPreimage(preimage)) {\n return null;\n }\n \n try {\n const timestampHex = preimage.slice(8, 16);\n const timestampSeconds = parseInt(timestampHex, 16);\n return timestampSeconds * 1000;\n } catch (error) {\n console.error('Failed to extract demo timestamp:', error);\n return null;\n }\n }\n\n // ============================================\n // VALIDATION AND CHECKS\n // ============================================\n\n validateSessionType(sessionType) {\n if (!sessionType || typeof sessionType !== 'string') {\n throw new Error('Session type must be a non-empty string');\n }\n \n if (!this.sessionPrices[sessionType]) {\n throw new Error(`Invalid session type: ${sessionType}. Allowed: ${Object.keys(this.sessionPrices).join(', ')}`);\n }\n \n const pricing = this.sessionPrices[sessionType];\n \n if (sessionType === 'demo') {\n return true;\n }\n \n if (pricing.sats < this.minimumPaymentSats) {\n throw new Error(`Session type ${sessionType} below minimum payment threshold (${this.minimumPaymentSats} sats)`);\n }\n \n return true;\n }\n\n calculateEntropy(str) {\n const freq = {};\n for (let char of str) {\n freq[char] = (freq[char] || 0) + 1;\n }\n \n let entropy = 0;\n const length = str.length;\n for (let char in freq) {\n const p = freq[char] / length;\n entropy -= p * Math.log2(p);\n }\n \n return entropy;\n }\n\n // ============================================\n // ENHANCED verification with additional checks\n // ============================================\n\n async verifyCryptographically(preimage, paymentHash) {\n try {\n // Basic validation\n if (!preimage || typeof preimage !== 'string' || preimage.length !== 64) {\n throw new Error('Invalid preimage format');\n }\n \n if (!/^[0-9a-fA-F]{64}$/.test(preimage)) {\n throw new Error('Preimage must be valid hexadecimal');\n }\n \n if (this.isDemoPreimage(preimage)) {\n console.log('\uD83C\uDFAE Demo preimage detected - performing ENHANCED validation...');\n \n // CHECK 1: Preimage duplicates\n if (this.usedPreimages.has(preimage)) {\n throw new Error('Demo preimage already used - replay attack prevented');\n }\n \n // CHECK 2: Global Activity\n if (this.activeDemoSessions.has(preimage)) {\n throw new Error('Demo preimage already active - concurrent usage prevented');\n }\n \n // CHECK 3: Timestamp validation\n const demoTimestamp = this.extractDemoTimestamp(preimage);\n if (!demoTimestamp) {\n throw new Error('Invalid demo preimage timestamp');\n }\n \n const now = Date.now();\n const age = now - demoTimestamp;\n \n // Demo preimage must not be older than 15 minutes\n if (age > 15 * 60 * 1000) {\n throw new Error(`Demo preimage expired (age: ${Math.round(age / (60 * 1000))} minutes)`);\n }\n\n if (age < -2 * 60 * 1000) {\n throw new Error('Demo preimage timestamp from future - possible clock manipulation');\n }\n \n // CHECK 4: FIXED calling limits - use the CORRECT method\n const userFingerprint = this.generateAdvancedUserFingerprint(); \n const limitsCheck = this.checkEnhancedDemoSessionLimits(userFingerprint); \n \n if (!limitsCheck.allowed) {\n throw new Error(`Demo session limits exceeded: ${limitsCheck.message}`);\n }\n \n // FIX: For demo sessions, do NOT add preimage to usedPreimages here,\n // as this will only be done after successful activation\n this.registerEnhancedDemoSessionUsage(userFingerprint, preimage); \n \n console.log('\u2705 Demo preimage ENHANCED validation passed');\n return true;\n }\n \n // For regular preimage - standard checks\n if (this.usedPreimages.has(preimage)) {\n throw new Error('Preimage already used - replay attack prevented');\n }\n \n // Checking entropy\n const entropy = this.calculateEntropy(preimage);\n if (entropy < 3.5) {\n throw new Error(`Preimage has insufficient entropy: ${entropy.toFixed(2)}`);\n }\n \n // Cryptographic verification SHA256(preimage) = paymentHash\n const preimageBytes = new Uint8Array(preimage.match(/.{2}/g).map(byte => parseInt(byte, 16)));\n const hashBuffer = await crypto.subtle.digest('SHA-256', preimageBytes);\n const computedHash = Array.from(new Uint8Array(hashBuffer))\n .map(b => b.toString(16).padStart(2, '0')).join('');\n \n const isValid = computedHash === paymentHash.toLowerCase();\n \n if (isValid) {\n this.usedPreimages.add(preimage);\n console.log('\u2705 Standard preimage cryptographic validation passed');\n }\n \n return isValid;\n \n } catch (error) {\n console.error('\u274C Cryptographic verification failed:', error.message);\n return false;\n }\n }\n\n\n // ============================================\n // LIGHTNING NETWORK INTEGRATION\n // ============================================\n\n // Creating a Lightning invoice\n async createLightningInvoice(sessionType) {\n const pricing = this.sessionPrices[sessionType];\n if (!pricing) throw new Error('Invalid session type');\n\n try {\n console.log(`Creating ${sessionType} invoice for ${pricing.sats} sats...`);\n\n const now = Date.now();\n if (now - this.lastApiCall < this.apiCallMinInterval) {\n throw new Error('API rate limit: please wait before next request');\n }\n this.lastApiCall = now;\n\n const healthCheck = await fetch(`${this.verificationConfig.apiUrl}/api/v1/health`, {\n method: 'GET',\n headers: {\n 'X-Api-Key': this.verificationConfig.apiKey\n },\n signal: AbortSignal.timeout(5000)\n });\n\n if (!healthCheck.ok) {\n throw new Error(`LNbits API unavailable: ${healthCheck.status}`);\n }\n\n const response = await fetch(`${this.verificationConfig.apiUrl}/api/v1/payments`, {\n method: 'POST',\n headers: {\n 'X-Api-Key': this.verificationConfig.apiKey,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n out: false,\n amount: pricing.sats,\n memo: `SecureBit.chat ${sessionType} session (${pricing.hours}h) - ${Date.now()}`,\n unit: 'sat',\n expiry: this.verificationConfig.invoiceExpiryMinutes * 60\n }),\n signal: AbortSignal.timeout(10000)\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('LNbits API error response:', errorText);\n throw new Error(`LNbits API error ${response.status}: ${errorText}`);\n }\n\n const data = await response.json();\n \n console.log('\u2705 Lightning invoice created successfully');\n \n return {\n paymentRequest: data.bolt11 || data.payment_request,\n paymentHash: data.payment_hash,\n checkingId: data.checking_id || data.payment_hash,\n amount: data.amount || pricing.sats,\n sessionType: sessionType,\n createdAt: Date.now(),\n expiresAt: Date.now() + (this.verificationConfig.invoiceExpiryMinutes * 60 * 1000),\n description: data.description || data.memo || `SecureBit.chat ${sessionType} session`,\n bolt11: data.bolt11 || data.payment_request,\n memo: data.memo || `SecureBit.chat ${sessionType} session`\n };\n\n } catch (error) {\n console.error('\u274C Lightning invoice creation failed:', error);\n \n if (this.verificationConfig.isDemo && error.message.includes('API')) {\n console.log('\uD83D\uDD04 Creating demo invoice for testing...');\n return this.createDemoInvoice(sessionType);\n }\n \n throw error;\n }\n }\n\n // Creating a demo invoice for testing\n createDemoInvoice(sessionType) {\n const pricing = this.sessionPrices[sessionType];\n const demoHash = Array.from(crypto.getRandomValues(new Uint8Array(32)))\n .map(b => b.toString(16).padStart(2, '0')).join('');\n \n return {\n paymentRequest: `lntb${pricing.sats}1p${demoHash.substring(0, 16)}...`,\n paymentHash: demoHash,\n checkingId: demoHash,\n amount: pricing.sats,\n sessionType: sessionType,\n createdAt: Date.now(),\n expiresAt: Date.now() + (5 * 60 * 1000),\n description: `SecureBit.chat ${sessionType} session (DEMO)`,\n isDemo: true\n };\n }\n\n // Checking payment status via LNbits\n async checkPaymentStatus(checkingId) {\n try {\n console.log(`\uD83D\uDD0D Checking payment status for: ${checkingId?.substring(0, 8)}...`);\n\n const now = Date.now();\n if (now - this.lastApiCall < this.apiCallMinInterval) {\n throw new Error('API rate limit exceeded');\n }\n this.lastApiCall = now;\n\n const response = await fetch(`${this.verificationConfig.apiUrl}/api/v1/payments/${checkingId}`, {\n method: 'GET',\n headers: {\n 'X-Api-Key': this.verificationConfig.apiKey,\n 'Content-Type': 'application/json'\n },\n signal: AbortSignal.timeout(10000)\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('Payment status check failed:', errorText);\n throw new Error(`Payment check failed: ${response.status} - ${errorText}`);\n }\n\n const data = await response.json();\n console.log('\uD83D\uDCCA Payment status retrieved successfully');\n \n return {\n paid: data.paid || false,\n preimage: data.preimage || null,\n details: data.details || {},\n amount: data.amount || 0,\n fee: data.fee || 0,\n timestamp: data.timestamp || Date.now(),\n bolt11: data.bolt11 || null\n };\n\n } catch (error) {\n console.error('\u274C Payment status check error:', error);\n \n if (this.verificationConfig.isDemo && error.message.includes('API')) {\n console.log('\uD83D\uDD04 Returning demo payment status...');\n return {\n paid: false,\n preimage: null,\n details: { demo: true },\n amount: 0,\n fee: 0,\n timestamp: Date.now()\n };\n }\n \n throw error;\n }\n }\n\n // Payment verification via LNbits API\n async verifyPaymentLNbits(preimage, paymentHash) {\n try {\n console.log(`\uD83D\uDD10 Verifying payment via LNbits API...`);\n \n if (!this.verificationConfig.apiUrl || !this.verificationConfig.apiKey) {\n throw new Error('LNbits API configuration missing');\n }\n\n const now = Date.now();\n if (now - this.lastApiCall < this.apiCallMinInterval) {\n throw new Error('API rate limit: please wait before next verification');\n }\n this.lastApiCall = now;\n\n const response = await fetch(`${this.verificationConfig.apiUrl}/api/v1/payments/${paymentHash}`, {\n method: 'GET',\n headers: {\n 'X-Api-Key': this.verificationConfig.apiKey,\n 'Content-Type': 'application/json'\n },\n signal: AbortSignal.timeout(10000)\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('LNbits verification failed:', errorText);\n throw new Error(`API request failed: ${response.status} - ${errorText}`);\n }\n\n const paymentData = await response.json();\n console.log('\uD83D\uDCCB Payment verification data received from LNbits');\n \n const isPaid = paymentData.paid === true;\n const preimageMatches = paymentData.preimage === preimage;\n const amountValid = paymentData.amount >= this.minimumPaymentSats;\n \n const paymentTimestamp = paymentData.timestamp || paymentData.time || 0;\n const paymentAge = now - (paymentTimestamp * 1000);\n const maxPaymentAge = 24 * 60 * 60 * 1000;\n \n if (paymentAge > maxPaymentAge && paymentTimestamp > 0) {\n throw new Error(`Payment too old: ${Math.round(paymentAge / (60 * 60 * 1000))} hours (max: 24h)`);\n }\n \n if (isPaid && preimageMatches && amountValid) {\n console.log('\u2705 Payment verified successfully via LNbits');\n return {\n verified: true,\n amount: paymentData.amount,\n fee: paymentData.fee || 0,\n timestamp: paymentTimestamp || now,\n method: 'lnbits',\n verificationTime: now,\n paymentAge: paymentAge\n };\n }\n\n console.log('\u274C LNbits payment verification failed:', {\n paid: isPaid,\n preimageMatch: preimageMatches,\n amountValid: amountValid,\n paymentAge: Math.round(paymentAge / (60 * 1000)) + ' minutes'\n });\n \n return {\n verified: false,\n reason: 'Payment verification failed: not paid, preimage mismatch, insufficient amount, or payment too old',\n method: 'lnbits',\n details: {\n paid: isPaid,\n preimageMatch: preimageMatches,\n amountValid: amountValid,\n paymentAge: paymentAge\n }\n };\n \n } catch (error) {\n console.error('\u274C LNbits payment verification failed:', error);\n return {\n verified: false,\n reason: error.message,\n method: 'lnbits',\n error: true\n };\n }\n }\n\n // ============================================\n // BASIC LOGIC OF PAYMENT VERIFICATION\n // ============================================\n\n // The main method of payment verification\n async verifyPayment(preimage, paymentHash) {\n console.log(`\uD83D\uDD10 Starting payment verification...`);\n \n try {\n if (!preimage || !paymentHash) {\n throw new Error('Missing preimage or payment hash');\n }\n \n if (typeof preimage !== 'string' || typeof paymentHash !== 'string') {\n throw new Error('Preimage and payment hash must be strings');\n }\n \n // Special demo preimage processing with ENHANCED checks\n if (this.isDemoPreimage(preimage)) {\n console.log('\uD83C\uDFAE Processing demo session verification...');\n \n // Cryptographic verification already includes all necessary checks\n const cryptoValid = await this.verifyCryptographically(preimage, paymentHash);\n if (!cryptoValid) {\n return { \n verified: false, \n reason: 'Demo preimage verification failed',\n stage: 'crypto'\n };\n }\n \n console.log('\u2705 Demo session verified successfully');\n return { \n verified: true, \n method: 'demo',\n sessionType: 'demo',\n isDemo: true,\n warning: 'Demo session - limited duration (6 minutes)'\n };\n }\n \n // Cryptographic verification for regular preimage\n const cryptoValid = await this.verifyCryptographically(preimage, paymentHash);\n if (!cryptoValid) {\n return { \n verified: false, \n reason: 'Cryptographic verification failed',\n stage: 'crypto'\n };\n }\n\n console.log('\u2705 Cryptographic verification passed');\n\n // Check via Lightning Network (if not demo mode)\n if (!this.verificationConfig.isDemo) {\n switch (this.verificationConfig.method) {\n case 'lnbits':\n const lnbitsResult = await this.verifyPaymentLNbits(preimage, paymentHash);\n if (!lnbitsResult.verified) {\n return {\n verified: false,\n reason: lnbitsResult.reason || 'LNbits verification failed',\n stage: 'lightning',\n details: lnbitsResult.details\n };\n }\n return lnbitsResult;\n \n default:\n console.warn('Unknown verification method, using crypto-only verification');\n return { \n verified: true, \n method: 'crypto-only',\n warning: 'Lightning verification skipped - unknown method'\n };\n }\n } else {\n console.warn('\uD83D\uDEA8 DEMO MODE: Lightning payment verification bypassed - FOR DEVELOPMENT ONLY');\n return { \n verified: true, \n method: 'demo-mode',\n warning: 'DEMO MODE - Lightning verification bypassed'\n };\n }\n \n } catch (error) {\n console.error('\u274C Payment verification failed:', error);\n return { \n verified: false, \n reason: error.message,\n stage: 'error'\n };\n }\n }\n\n // ============================================\n // SESSION MANAGEMENT\n // ============================================\n\n // ============================================\n // REWORKED session activation methods\n // ============================================\n\n async safeActivateSession(sessionType, preimage, paymentHash) {\n try {\n console.log(`\uD83D\uDE80 Attempting to activate ${sessionType} session...`);\n \n if (!sessionType || !preimage || !paymentHash) {\n return { \n success: false, \n reason: 'Missing required parameters: sessionType, preimage, or paymentHash' \n };\n }\n \n try {\n this.validateSessionType(sessionType);\n } catch (error) {\n return { success: false, reason: error.message };\n }\n \n if (this.hasActiveSession()) {\n return { \n success: false, \n reason: 'Active session already exists. Please wait for it to expire or disconnect.' \n };\n }\n \n if (sessionType === 'demo') {\n if (!this.isDemoPreimage(preimage)) {\n return {\n success: false,\n reason: 'Invalid demo preimage format. Please use the generated demo preimage.'\n };\n }\n \n const userFingerprint = this.generateAdvancedUserFingerprint();\n const demoCheck = this.checkEnhancedDemoSessionLimits(userFingerprint);\n \n if (!demoCheck.allowed) {\n console.log(`\u26A0\uFE0F Demo session cooldown active, but allowing activation for development`);\n \n if (demoCheck.reason === 'global_limit_exceeded') {\n return {\n success: false,\n reason: demoCheck.message,\n demoLimited: true,\n timeUntilNext: demoCheck.timeUntilNext,\n remaining: demoCheck.remaining\n };\n }\n \n console.log(`\uD83D\uDD04 Bypassing demo cooldown for development purposes`);\n }\n \n if (this.activeDemoSessions.has(preimage)) {\n if (!this.currentSession || !this.hasActiveSession()) {\n console.log(`\uD83D\uDD04 Demo session with preimage ${preimage.substring(0, 16)}... was interrupted, allowing reactivation`);\n this.activeDemoSessions.delete(preimage);\n } else {\n return {\n success: false,\n reason: 'Demo session with this preimage is already active',\n demoLimited: true\n };\n }\n }\n }\n \n let verificationResult;\n \n if (sessionType === 'demo') {\n console.log('\uD83C\uDFAE Using special demo verification for activation...');\n verificationResult = await this.verifyDemoSessionForActivation(preimage, paymentHash);\n } else {\n verificationResult = await this.verifyPayment(preimage, paymentHash);\n }\n \n if (!verificationResult.verified) {\n return {\n success: false,\n reason: verificationResult.reason,\n stage: verificationResult.stage,\n method: verificationResult.method,\n demoLimited: verificationResult.demoLimited,\n timeUntilNext: verificationResult.timeUntilNext,\n remaining: verificationResult.remaining\n };\n }\n \n // Session activation\n const session = this.activateSession(sessionType, preimage);\n \n console.log(`\u2705 Session activated successfully: ${sessionType} via ${verificationResult.method}`);\n return {\n success: true,\n sessionType: sessionType,\n method: verificationResult.method,\n details: verificationResult,\n timeLeft: this.getTimeLeft(),\n sessionId: session.id,\n warning: verificationResult.warning,\n isDemo: verificationResult.isDemo || false,\n remaining: verificationResult.remaining\n };\n \n } catch (error) {\n console.error('\u274C Session activation failed:', error);\n return {\n success: false,\n reason: error.message,\n method: 'error'\n };\n }\n }\n\n // REWORKED session activation\n activateSession(sessionType, preimage) {\n if (this.hasActiveSession()) {\n return this.currentSession;\n }\n if (this.sessionTimer) {\n clearInterval(this.sessionTimer);\n this.sessionTimer = null;\n }\n\n const pricing = this.sessionPrices[sessionType];\n const now = Date.now();\n \n let duration;\n if (sessionType === 'demo') {\n duration = this.demoSessionMaxDuration;\n } else {\n duration = pricing.hours * 60 * 60 * 1000;\n }\n \n const expiresAt = now + duration;\n const sessionId = Array.from(crypto.getRandomValues(new Uint8Array(16)))\n .map(b => b.toString(16).padStart(2, '0')).join('');\n\n this.currentSession = {\n id: sessionId,\n type: sessionType,\n startTime: now,\n expiresAt: expiresAt,\n preimage: preimage,\n isDemo: sessionType === 'demo',\n securityLevel: this.getSecurityLevelForSession(sessionType)\n };\n\n this.startSessionTimer();\n \n if (sessionType === 'demo') {\n setTimeout(() => {\n this.handleDemoSessionExpiry(preimage);\n }, duration);\n }\n \n const durationMinutes = Math.round(duration / (60 * 1000));\n const securityLevel = this.currentSession ? this.currentSession.securityLevel : 'unknown';\n console.log(`\uD83D\uDCC5 Session ${sessionId.substring(0, 8)}... activated for ${durationMinutes} minutes with ${securityLevel} security`);\n \n if (sessionType === 'demo') {\n this.activeDemoSessions.add(preimage);\n this.usedPreimages.add(preimage);\n console.log(`\uD83C\uDF10 Demo session added to active sessions. Total: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`);\n }\n \n // SENDING SECURITY LEVEL INFORMATION TO WebRTC\n const activatedSession = this.currentSession; \n setTimeout(() => {\n if (activatedSession) {\n this.notifySessionActivated(activatedSession);\n }\n // Notify WebRTC manager about session type\n if (window.webrtcManager && window.webrtcManager.configureSecurityForSession && activatedSession) {\n const securityLevel = activatedSession.securityLevel || this.getSecurityLevelForSession(sessionType);\n window.webrtcManager.configureSecurityForSession(sessionType, securityLevel);\n }\n }, 100);\n \n return this.currentSession;\n }\n\n // UPDATED method for getting session information\n getSessionInfo() {\n if (!this.currentSession) {\n return null;\n }\n\n const securityLevel = this.getSecurityLevelForSession(this.currentSession.type);\n const pricing = this.sessionPrices[this.currentSession.type];\n\n return {\n ...this.currentSession,\n securityLevel: securityLevel,\n securityDescription: this.getSecurityDescription(securityLevel),\n pricing: pricing,\n timeLeft: this.getTimeLeft(),\n isConnected: this.hasActiveSession()\n };\n }\n\n getSecurityDescription(level) {\n const descriptions = {\n 'basic': {\n title: 'Basic Security',\n features: [\n 'End-to-end encryption',\n 'Basic key exchange',\n 'Rate limiting',\n 'Message integrity'\n ],\n limitations: [\n 'No advanced obfuscation',\n 'No traffic padding',\n 'No decoy channels'\n ]\n },\n 'enhanced': {\n title: 'Enhanced Security',\n features: [\n 'All basic features',\n 'ECDSA signatures',\n 'Metadata protection',\n 'Perfect forward secrecy',\n 'Nested encryption',\n 'Packet padding'\n ],\n limitations: [\n 'Limited traffic obfuscation',\n 'No fake traffic generation'\n ]\n },\n 'maximum': {\n title: 'Maximum Security',\n features: [\n 'All enhanced features',\n 'Traffic obfuscation',\n 'Fake traffic generation',\n 'Decoy channels',\n 'Anti-fingerprinting',\n 'Message chunking',\n 'Packet reordering protection'\n ],\n limitations: []\n }\n };\n\n return descriptions[level] || descriptions['basic'];\n }\n\n notifySessionActivated(session = null) {\n const targetSession = session || this.currentSession;\n\n if (!targetSession) return;\n if (targetSession.notified) {\n return;\n }\n \n const timeLeft = Math.max(0, targetSession.expiresAt - Date.now());\n const sessionType = targetSession.type;\n \n\n \n if (window.updateSessionTimer) {\n window.updateSessionTimer(timeLeft, sessionType);\n }\n \n document.dispatchEvent(new CustomEvent('session-activated', {\n detail: {\n sessionId: targetSession.id,\n timeLeft: timeLeft,\n sessionType: sessionType,\n isDemo: targetSession.isDemo,\n timestamp: Date.now()\n }\n }));\n \n if (window.forceUpdateHeader) {\n window.forceUpdateHeader(timeLeft, sessionType);\n }\n\n if (window.debugSessionManager) {\n window.debugSessionManager();\n }\n targetSession.notified = true;\n }\n\n handleDemoSessionExpiry(preimage) {\n if (this.currentSession && this.currentSession.preimage === preimage) {\n const userFingerprint = this.generateAdvancedUserFingerprint(); \n const sessionDuration = Date.now() - this.currentSession.startTime;\n \n this.registerDemoSessionCompletion(userFingerprint, sessionDuration, preimage);\n \n console.log(`\u23F0 Demo session auto-expired for preimage ${preimage.substring(0, 16)}...`);\n }\n }\n\n startSessionTimer() {\n if (this.sessionTimer) {\n clearInterval(this.sessionTimer);\n }\n\n this.sessionTimer = setInterval(() => {\n if (!this.hasActiveSession()) {\n this.expireSession();\n }\n }, 60000);\n }\n\n expireSession() {\n if (this.sessionTimer) {\n clearInterval(this.sessionTimer);\n this.sessionTimer = null;\n }\n \n const expiredSession = this.currentSession;\n \n if (expiredSession && expiredSession.isDemo) {\n const userFingerprint = this.generateAdvancedUserFingerprint(); \n const sessionDuration = Date.now() - expiredSession.startTime;\n this.registerDemoSessionCompletion(userFingerprint, sessionDuration, expiredSession.preimage);\n }\n \n this.currentSession = null;\n \n if (expiredSession) {\n console.log(`\u23F0 Session ${expiredSession.id.substring(0, 8)}... expired`);\n }\n \n if (this.onSessionExpired) {\n this.onSessionExpired();\n }\n }\n\n hasActiveSession() {\n if (!this.currentSession) {\n return false;\n }\n \n const isActive = Date.now() < this.currentSession.expiresAt;\n \n return isActive;\n }\n\n getTimeLeft() {\n if (!this.currentSession) return 0;\n return Math.max(0, this.currentSession.expiresAt - Date.now());\n }\n\n forceUpdateTimer() {\n if (this.currentSession) {\n const timeLeft = this.getTimeLeft();\n if (window.DEBUG_MODE && Math.floor(Date.now() / 30000) !== Math.floor((Date.now() - 1000) / 30000)) {\n console.log(`\u23F1\uFE0F Timer updated: ${Math.ceil(timeLeft / 1000)}s left`);\n }\n return timeLeft;\n }\n return 0;\n }\n\n // ============================================\n // DEMO MODE: Custom Methods\n // ============================================\n\n // UPDATED demo session creation\n createDemoSession() {\n const userFingerprint = this.generateAdvancedUserFingerprint(); \n const demoCheck = this.checkEnhancedDemoSessionLimits(userFingerprint); \n \n if (!demoCheck.allowed) {\n return {\n success: false,\n reason: demoCheck.message,\n timeUntilNext: demoCheck.timeUntilNext,\n remaining: demoCheck.remaining,\n blockingReason: demoCheck.reason\n };\n }\n \n // Checking the global limit\n if (this.activeDemoSessions.size >= this.maxGlobalDemoSessions) {\n return {\n success: false,\n reason: `Too many demo sessions active globally (${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}). Please try again later.`,\n blockingReason: 'global_limit',\n globalActive: this.activeDemoSessions.size,\n globalLimit: this.maxGlobalDemoSessions\n };\n }\n \n try {\n const demoPreimage = this.generateSecureDemoPreimage();\n const demoPaymentHash = 'demo_' + Array.from(crypto.getRandomValues(new Uint8Array(16)))\n .map(b => b.toString(16).padStart(2, '0')).join('');\n \n return {\n success: true,\n sessionType: 'demo',\n preimage: demoPreimage,\n paymentHash: demoPaymentHash,\n duration: this.sessionPrices.demo.hours,\n durationMinutes: Math.round(this.demoSessionMaxDuration / (60 * 1000)),\n warning: `Demo session - limited to ${Math.round(this.demoSessionMaxDuration / (60 * 1000))} minutes`,\n remaining: demoCheck.remaining - 1,\n globalActive: this.activeDemoSessions.size + 1,\n globalLimit: this.maxGlobalDemoSessions\n };\n } catch (error) {\n console.error('Failed to create demo session:', error);\n return {\n success: false,\n reason: 'Failed to generate demo session. Please try again.',\n remaining: demoCheck.remaining\n };\n }\n }\n\n\n // UPDATED information about demo limits\n getDemoSessionInfo() {\n const userFingerprint = this.generateAdvancedUserFingerprint(); \n const userData = this.demoSessions.get(userFingerprint);\n const now = Date.now();\n \n if (!userData) {\n return {\n available: this.maxDemoSessionsPerUser,\n used: 0,\n total: this.maxDemoSessionsPerUser,\n nextAvailable: 'immediately',\n cooldownMinutes: 0,\n durationMinutes: Math.round(this.demoSessionMaxDuration / (60 * 1000)),\n canUseNow: this.activeDemoSessions.size < this.maxGlobalDemoSessions,\n globalActive: this.activeDemoSessions.size,\n globalLimit: this.maxGlobalDemoSessions,\n debugInfo: 'New user, no restrictions'\n };\n }\n \n // Counting sessions for the last 24 hours\n const sessionsLast24h = userData.sessions.filter(session => \n now - session.timestamp < this.demoCooldownPeriod\n );\n \n const available = Math.max(0, this.maxDemoSessionsPerUser - sessionsLast24h.length);\n \n // We check all possible blockages\n let cooldownMs = 0;\n let nextAvailable = 'immediately';\n let blockingReason = null;\n let debugInfo = '';\n \n // Global limit\n if (this.activeDemoSessions.size >= this.maxGlobalDemoSessions) {\n nextAvailable = 'when global limit decreases';\n blockingReason = 'global_limit';\n debugInfo = `Global limit: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`;\n }\n // Daily limit\n else if (available === 0) {\n const oldestSession = Math.min(...sessionsLast24h.map(s => s.timestamp));\n cooldownMs = this.demoCooldownPeriod - (now - oldestSession);\n nextAvailable = `${Math.ceil(cooldownMs / (60 * 1000))} minutes`;\n blockingReason = 'daily_limit';\n debugInfo = `Daily limit reached: ${sessionsLast24h.length}/${this.maxDemoSessionsPerUser}`;\n }\n // Cooldown between sessions\n else if (userData.lastUsed && (now - userData.lastUsed) < this.demoSessionCooldown) {\n cooldownMs = this.demoSessionCooldown - (now - userData.lastUsed);\n nextAvailable = `${Math.ceil(cooldownMs / (60 * 1000))} minutes`;\n blockingReason = 'session_cooldown';\n const lastUsedMinutes = Math.round((now - userData.lastUsed) / (60 * 1000));\n debugInfo = `Cooldown active: last used ${lastUsedMinutes}min ago, need ${Math.ceil(cooldownMs / (60 * 1000))}min more`;\n }\n // Cooldown after completed session\n else {\n const completedSessions = this.completedDemoSessions.get(userFingerprint) || [];\n const recentCompletedSessions = completedSessions.filter(session =>\n now - session.endTime < this.minTimeBetweenCompletedSessions\n );\n \n if (recentCompletedSessions.length > 0) {\n const lastCompletedSession = Math.max(...recentCompletedSessions.map(s => s.endTime));\n cooldownMs = this.minTimeBetweenCompletedSessions - (now - lastCompletedSession);\n nextAvailable = `${Math.ceil(cooldownMs / (60 * 1000))} minutes`;\n blockingReason = 'completion_cooldown';\n const completedMinutes = Math.round((now - lastCompletedSession) / (60 * 1000));\n debugInfo = `Completion cooldown: last session ended ${completedMinutes}min ago`;\n } else {\n debugInfo = `Ready to use: ${available} sessions available`;\n }\n }\n \n const canUseNow = available > 0 && \n cooldownMs <= 0 && \n this.activeDemoSessions.size < this.maxGlobalDemoSessions;\n \n return {\n available: available,\n used: sessionsLast24h.length,\n total: this.maxDemoSessionsPerUser,\n nextAvailable: nextAvailable,\n cooldownMinutes: Math.ceil(cooldownMs / (60 * 1000)),\n durationMinutes: Math.round(this.demoSessionMaxDuration / (60 * 1000)),\n canUseNow: canUseNow,\n blockingReason: blockingReason,\n globalActive: this.activeDemoSessions.size,\n globalLimit: this.maxGlobalDemoSessions,\n completionCooldownMinutes: Math.round(this.minTimeBetweenCompletedSessions / (60 * 1000)),\n sessionCooldownMinutes: Math.round(this.demoSessionCooldown / (60 * 1000)),\n debugInfo: debugInfo,\n lastUsed: userData.lastUsed ? new Date(userData.lastUsed).toLocaleString() : 'Never'\n };\n }\n\n\n\n // ============================================\n // ADDITIONAL VERIFICATION METHODS\n // ============================================\n\n // Verification method via LND (Lightning Network Daemon)\n async verifyPaymentLND(preimage, paymentHash) {\n try {\n if (!this.verificationConfig.nodeUrl || !this.verificationConfig.macaroon) {\n throw new Error('LND configuration missing');\n }\n\n const response = await fetch(`${this.verificationConfig.nodeUrl}/v1/invoice/${paymentHash}`, {\n method: 'GET',\n headers: {\n 'Grpc-Metadata-macaroon': this.verificationConfig.macaroon,\n 'Content-Type': 'application/json'\n },\n signal: AbortSignal.timeout(10000)\n });\n\n if (!response.ok) {\n throw new Error(`LND API request failed: ${response.status}`);\n }\n\n const invoiceData = await response.json();\n \n if (invoiceData.settled && invoiceData.r_preimage === preimage) {\n return {\n verified: true,\n amount: invoiceData.value,\n method: 'lnd',\n timestamp: Date.now()\n };\n }\n\n return { verified: false, reason: 'LND verification failed', method: 'lnd' };\n } catch (error) {\n console.error('LND payment verification failed:', error);\n return { verified: false, reason: error.message, method: 'lnd' };\n }\n }\n\n // Verification method via CLN (Core Lightning)\n async verifyPaymentCLN(preimage, paymentHash) {\n try {\n if (!this.verificationConfig.nodeUrl) {\n throw new Error('CLN configuration missing');\n }\n\n const response = await fetch(`${this.verificationConfig.nodeUrl}/v1/listinvoices`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n payment_hash: paymentHash\n }),\n signal: AbortSignal.timeout(10000)\n });\n\n if (!response.ok) {\n throw new Error(`CLN API request failed: ${response.status}`);\n }\n\n const data = await response.json();\n \n if (data.invoices && data.invoices.length > 0) {\n const invoice = data.invoices[0];\n if (invoice.status === 'paid' && invoice.payment_preimage === preimage) {\n return {\n verified: true,\n amount: invoice.amount_msat / 1000,\n method: 'cln',\n timestamp: Date.now()\n };\n }\n }\n\n return { verified: false, reason: 'CLN verification failed', method: 'cln' };\n } catch (error) {\n console.error('CLN payment verification failed:', error);\n return { verified: false, reason: error.message, method: 'cln' };\n }\n }\n\n // Verification method via BTCPay Server\n async verifyPaymentBTCPay(preimage, paymentHash) {\n try {\n if (!this.verificationConfig.apiUrl || !this.verificationConfig.apiKey) {\n throw new Error('BTCPay Server configuration missing');\n }\n\n const response = await fetch(`${this.verificationConfig.apiUrl}/api/v1/invoices/${paymentHash}`, {\n method: 'GET',\n headers: {\n 'Authorization': `Bearer ${this.verificationConfig.apiKey}`,\n 'Content-Type': 'application/json'\n },\n signal: AbortSignal.timeout(10000)\n });\n\n if (!response.ok) {\n throw new Error(`BTCPay API request failed: ${response.status}`);\n }\n\n const invoiceData = await response.json();\n \n if (invoiceData.status === 'Settled' && \n invoiceData.payment && \n invoiceData.payment.preimage === preimage) {\n return {\n verified: true,\n amount: invoiceData.amount,\n method: 'btcpay',\n timestamp: Date.now()\n };\n }\n\n return { verified: false, reason: 'BTCPay verification failed', method: 'btcpay' };\n } catch (error) {\n console.error('BTCPay payment verification failed:', error);\n return { verified: false, reason: error.message, method: 'btcpay' };\n }\n }\n\n // ============================================\n // UTILITY METHODS\n // ============================================\n\n // Creating a regular invoice (not a demo)\n createInvoice(sessionType) {\n this.validateSessionType(sessionType);\n const pricing = this.sessionPrices[sessionType];\n\n const randomBytes = crypto.getRandomValues(new Uint8Array(32));\n const timestamp = Date.now();\n const sessionEntropy = crypto.getRandomValues(new Uint8Array(16));\n \n const combinedEntropy = new Uint8Array(48);\n combinedEntropy.set(randomBytes, 0);\n combinedEntropy.set(new Uint8Array(new BigUint64Array([BigInt(timestamp)]).buffer), 32);\n combinedEntropy.set(sessionEntropy, 40);\n \n const paymentHash = Array.from(crypto.getRandomValues(new Uint8Array(32)))\n .map(b => b.toString(16).padStart(2, '0')).join('');\n\n return {\n amount: pricing.sats,\n memo: `SecureBit.chat ${sessionType} session (${pricing.hours}h) - ${timestamp}`,\n sessionType: sessionType,\n timestamp: timestamp,\n paymentHash: paymentHash,\n lightningAddress: this.staticLightningAddress,\n entropy: Array.from(sessionEntropy).map(b => b.toString(16).padStart(2, '0')).join(''),\n expiresAt: timestamp + (this.verificationConfig.invoiceExpiryMinutes * 60 * 1000)\n };\n }\n\n // Checking if a session can be activated\n canActivateSession() {\n return !this.hasActiveSession();\n }\n\n // Reset session (if there are security errors)\n resetSession() {\n if (this.sessionTimer) {\n clearInterval(this.sessionTimer);\n this.sessionTimer = null;\n }\n \n const resetSession = this.currentSession;\n \n // IMPORTANT: For demo sessions, we register forced termination\n if (resetSession && resetSession.isDemo) {\n const userFingerprint = this.generateAdvancedUserFingerprint(); \n const sessionDuration = Date.now() - resetSession.startTime;\n this.registerDemoSessionCompletion(userFingerprint, sessionDuration, resetSession.preimage);\n }\n \n this.currentSession = null;\n this.sessionStartTime = null;\n this.sessionEndTime = null;\n \n if (resetSession && resetSession.preimage) {\n this.activeDemoSessions.delete(resetSession.preimage);\n }\n \n document.dispatchEvent(new CustomEvent('session-reset', {\n detail: { \n timestamp: Date.now(),\n reason: 'security_reset'\n }\n }));\n \n setTimeout(() => {\n if (this.currentSession) {\n this.currentSession = null;\n }\n }, 100);\n }\n\n // Cleaning old preimages (every 24 hours)\n startPreimageCleanup() {\n this.preimageCleanupInterval = setInterval(() => {\n if (this.usedPreimages.size > 10000) {\n const oldSize = this.usedPreimages.size;\n this.usedPreimages.clear();\n console.log(`\uD83E\uDDF9 Cleaned ${oldSize} old preimages for memory management`);\n }\n }, 24 * 60 * 60 * 1000);\n }\n\n // Complete manager cleanup\n cleanup() {\n if (this.sessionTimer) {\n clearInterval(this.sessionTimer);\n this.sessionTimer = null;\n }\n if (this.preimageCleanupInterval) {\n clearInterval(this.preimageCleanupInterval);\n this.preimageCleanupInterval = null;\n }\n \n // IMPORTANT: We register the end of the current demo session during cleanup\n if (this.currentSession && this.currentSession.isDemo) {\n const userFingerprint = this.generateAdvancedUserFingerprint(); \n const sessionDuration = Date.now() - this.currentSession.startTime;\n this.registerDemoSessionCompletion(userFingerprint, sessionDuration, this.currentSession.preimage);\n }\n \n this.currentSession = null;\n this.sessionStartTime = null;\n this.sessionEndTime = null;\n \n if (this.currentSession && this.currentSession.preimage) {\n this.activeDemoSessions.delete(this.currentSession.preimage);\n }\n \n document.dispatchEvent(new CustomEvent('session-cleanup', {\n detail: { \n timestamp: Date.now(),\n reason: 'complete_cleanup'\n }\n }));\n \n setTimeout(() => {\n if (this.currentSession) {\n this.currentSession = null;\n }\n }, 100);\n }\n\n getUsageStats() {\n const stats = {\n totalDemoUsers: this.demoSessions.size,\n usedPreimages: this.usedPreimages.size,\n activeDemoSessions: this.activeDemoSessions.size,\n globalDemoLimit: this.maxGlobalDemoSessions,\n currentSession: this.currentSession ? {\n type: this.currentSession.type,\n timeLeft: this.getTimeLeft(),\n isDemo: this.currentSession.isDemo\n } : null,\n config: {\n maxDemoSessions: this.maxDemoSessionsPerUser,\n demoCooldown: this.demoSessionCooldown / (60 * 1000),\n demoMaxDuration: this.demoSessionMaxDuration / (60 * 1000),\n completionCooldown: this.minTimeBetweenCompletedSessions / (60 * 1000)\n }\n };\n \n return stats;\n }\n\n getVerifiedDemoSession() {\n const userFingerprint = this.generateAdvancedUserFingerprint(); \n const userData = this.demoSessions.get(userFingerprint);\n \n console.log('\uD83D\uDD0D Searching for verified demo session:', {\n userFingerprint: userFingerprint.substring(0, 12),\n hasUserData: !!userData,\n sessionsCount: userData?.sessions?.length || 0,\n currentSession: this.currentSession ? {\n type: this.currentSession.type,\n timeLeft: this.getTimeLeft(),\n isActive: this.hasActiveSession()\n } : null\n });\n \n if (!userData || !userData.sessions || userData.sessions.length === 0) {\n console.log('\u274C No user data or sessions found');\n return null;\n }\n\n const lastSession = userData.sessions[userData.sessions.length - 1];\n if (!lastSession || !lastSession.preimage) {\n console.log('\u274C Last session is invalid:', lastSession);\n return null;\n }\n \n if (!this.isDemoPreimage(lastSession.preimage)) {\n console.log('\u274C Last session preimage is not demo format:', lastSession.preimage.substring(0, 16) + '...');\n return null;\n }\n \n if (this.activeDemoSessions.has(lastSession.preimage)) {\n console.log('\u26A0\uFE0F Demo session is already in activeDemoSessions, checking if truly active...');\n if (this.hasActiveSession()) {\n console.log('\u274C Demo session is truly active, cannot reactivate');\n return null;\n } else {\n console.log('\uD83D\uDD04 Demo session was interrupted, can be reactivated');\n }\n }\n \n const verifiedSession = {\n preimage: lastSession.preimage,\n paymentHash: lastSession.paymentHash || 'demo_' + Date.now(),\n sessionType: 'demo',\n timestamp: lastSession.timestamp\n };\n \n console.log('\u2705 Found verified demo session:', {\n preimage: verifiedSession.preimage.substring(0, 16) + '...',\n timestamp: new Date(verifiedSession.timestamp).toLocaleTimeString(),\n canActivate: !this.hasActiveSession()\n });\n \n return verifiedSession;\n }\n\n checkDemoSessionLimits(userFingerprint) {\n const userData = this.demoSessions.get(userFingerprint);\n const now = Date.now();\n \n console.log(`\uD83D\uDD0D Checking demo limits for user ${userFingerprint.substring(0, 12)}...`);\n \n // CHECK 1: Global limit of simultaneous demo sessions\n if (this.activeDemoSessions.size >= this.maxGlobalDemoSessions) {\n console.log(`\u274C Global demo limit reached: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`);\n return {\n allowed: false,\n reason: 'global_limit_exceeded',\n message: `Too many demo sessions active globally (${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}). Please try again later.`,\n remaining: 0,\n debugInfo: `Global sessions: ${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}`\n };\n }\n \n if (!userData) {\n // First demo session for this user\n console.log(`\u2705 First demo session for user ${userFingerprint.substring(0, 12)}`);\n return { \n allowed: true, \n reason: 'first_demo_session',\n remaining: this.maxDemoSessionsPerUser,\n debugInfo: 'First time user'\n };\n }\n \n // CHECK 2: Limit sessions per 24 hours (STRICT check)\n const sessionsLast24h = userData.sessions.filter(session => \n now - session.timestamp < this.demoCooldownPeriod\n );\n \n console.log(`\uD83D\uDCCA Sessions in last 24h for user ${userFingerprint.substring(0, 12)}: ${sessionsLast24h.length}/${this.maxDemoSessionsPerUser}`);\n \n if (sessionsLast24h.length >= this.maxDemoSessionsPerUser) {\n const oldestSession = Math.min(...sessionsLast24h.map(s => s.timestamp));\n const timeUntilNext = this.demoCooldownPeriod - (now - oldestSession);\n \n console.log(`\u274C Daily demo limit exceeded for user ${userFingerprint.substring(0, 12)}`);\n return { \n allowed: false, \n reason: 'daily_limit_exceeded',\n timeUntilNext: timeUntilNext,\n message: `Daily demo limit reached (${this.maxDemoSessionsPerUser}/day). Next session available in ${Math.ceil(timeUntilNext / (60 * 1000))} minutes.`,\n remaining: 0,\n debugInfo: `Used ${sessionsLast24h.length}/${this.maxDemoSessionsPerUser} today`\n };\n }\n \n // CHECK 3: Cooldown between sessions (FIXED LOGIC)\n if (userData.lastUsed && (now - userData.lastUsed) < this.demoSessionCooldown) {\n const timeUntilNext = this.demoSessionCooldown - (now - userData.lastUsed);\n const minutesLeft = Math.ceil(timeUntilNext / (60 * 1000));\n \n console.log(`\u23F0 Cooldown active for user ${userFingerprint.substring(0, 12)}: ${minutesLeft} minutes`);\n \n return { \n allowed: false, \n reason: 'session_cooldown',\n timeUntilNext: timeUntilNext,\n message: `Please wait ${minutesLeft} minutes between demo sessions. This prevents abuse and ensures fair access for all users.`,\n remaining: this.maxDemoSessionsPerUser - sessionsLast24h.length,\n debugInfo: `Cooldown: ${minutesLeft}min left, last used: ${Math.round((now - userData.lastUsed) / (60 * 1000))}min ago`\n };\n }\n \n // CHECK 4: NEW - Check for completed sessions\n const completedSessions = this.completedDemoSessions.get(userFingerprint) || [];\n const recentCompletedSessions = completedSessions.filter(session =>\n now - session.endTime < this.minTimeBetweenCompletedSessions\n );\n \n if (recentCompletedSessions.length > 0) {\n const lastCompletedSession = Math.max(...recentCompletedSessions.map(s => s.endTime));\n const timeUntilNext = this.minTimeBetweenCompletedSessions - (now - lastCompletedSession);\n \n console.log(`\u23F0 Recent session completed, waiting period active for user ${userFingerprint.substring(0, 12)}`);\n return {\n allowed: false,\n reason: 'recent_session_completed',\n timeUntilNext: timeUntilNext,\n message: `Please wait ${Math.ceil(timeUntilNext / (60 * 1000))} minutes after your last session before starting a new one.`,\n remaining: this.maxDemoSessionsPerUser - sessionsLast24h.length,\n debugInfo: `Last session ended ${Math.round((now - lastCompletedSession) / (60 * 1000))}min ago`\n };\n }\n \n console.log(`\u2705 Demo session approved for user ${userFingerprint.substring(0, 12)}`);\n return { \n allowed: true, \n reason: 'within_limits',\n remaining: this.maxDemoSessionsPerUser - sessionsLast24h.length,\n debugInfo: `Available: ${this.maxDemoSessionsPerUser - sessionsLast24h.length}/${this.maxDemoSessionsPerUser}`\n };\n }\n\n createDemoSessionForActivation() {\n const userFingerprint = this.generateAdvancedUserFingerprint(); // \u0418\u0421\u041F\u0420\u0410\u0412\u041B\u0415\u041D\u041E!\n \n if (this.activeDemoSessions.size >= this.maxGlobalDemoSessions) {\n return {\n success: false,\n reason: `Too many demo sessions active globally (${this.activeDemoSessions.size}/${this.maxGlobalDemoSessions}). Please try again later.`,\n blockingReason: 'global_limit'\n };\n }\n \n try {\n const demoPreimage = this.generateSecureDemoPreimage();\n const demoPaymentHash = 'demo_' + Array.from(crypto.getRandomValues(new Uint8Array(16)))\n .map(b => b.toString(16).padStart(2, '0')).join('');\n \n console.log('\uD83D\uDD04 Created demo session for activation:', {\n preimage: demoPreimage.substring(0, 16) + '...',\n paymentHash: demoPaymentHash.substring(0, 16) + '...'\n });\n \n return {\n success: true,\n sessionType: 'demo',\n preimage: demoPreimage,\n paymentHash: demoPaymentHash,\n duration: this.sessionPrices.demo.hours,\n durationMinutes: Math.round(this.demoSessionMaxDuration / (60 * 1000)),\n warning: `Demo session - limited to ${Math.round(this.demoSessionMaxDuration / (60 * 1000))} minutes`,\n globalActive: this.activeDemoSessions.size + 1,\n globalLimit: this.maxGlobalDemoSessions\n };\n } catch (error) {\n console.error('Failed to create demo session for activation:', error);\n return {\n success: false,\n reason: 'Failed to generate demo session for activation. Please try again.'\n };\n }\n }\n\n async verifyDemoSessionForActivation(preimage, paymentHash) {\n console.log('\uD83C\uDFAE Verifying demo session for activation (bypassing limits)...');\n \n try {\n if (!preimage || !paymentHash) {\n throw new Error('Missing preimage or payment hash');\n }\n \n if (typeof preimage !== 'string' || typeof paymentHash !== 'string') {\n throw new Error('Preimage and payment hash must be strings');\n }\n \n if (!this.isDemoPreimage(preimage)) {\n throw new Error('Invalid demo preimage format');\n }\n \n const entropy = this.calculateEntropy(preimage);\n if (entropy < 3.5) {\n throw new Error(`Demo preimage has insufficient entropy: ${entropy.toFixed(2)}`);\n }\n \n if (this.activeDemoSessions.has(preimage)) {\n throw new Error('Demo session with this preimage is already active');\n }\n \n console.log('\u2705 Demo session verified for activation successfully');\n return { \n verified: true, \n method: 'demo-activation',\n sessionType: 'demo',\n isDemo: true,\n warning: 'Demo session - limited duration (6 minutes)'\n };\n \n } catch (error) {\n console.error('\u274C Demo session verification for activation failed:', error);\n return { \n verified: false, \n reason: error.message,\n stage: 'demo-activation'\n };\n }\n }\n}\n\nexport { PayPerSessionManager };", "// SessionTimer Component - v4.02.985 - ECDH + DTLS + SAS\nconst SessionTimer = ({ timeLeft, sessionType, sessionManager, onDisconnect }) => {\n const [currentTime, setCurrentTime] = React.useState(timeLeft || 0);\n const [showExpiredMessage, setShowExpiredMessage] = React.useState(false);\n const [initialized, setInitialized] = React.useState(false);\n const [connectionBroken, setConnectionBroken] = React.useState(false);\n \n\n const [loggedHidden, setLoggedHidden] = React.useState(false);\n\n React.useEffect(() => {\n if (connectionBroken) {\n if (!loggedHidden) {\n console.log('\u23F1\uFE0F SessionTimer initialization skipped - connection broken');\n setLoggedHidden(true);\n }\n return;\n }\n \n let initialTime = 0;\n \n if (sessionManager?.hasActiveSession()) {\n initialTime = sessionManager.getTimeLeft();\n } else if (timeLeft && timeLeft > 0) {\n initialTime = timeLeft;\n }\n\n if (initialTime <= 0) {\n setCurrentTime(0);\n setInitialized(false);\n setLoggedHidden(true);\n return;\n }\n\n if (connectionBroken) {\n setCurrentTime(0);\n setInitialized(false);\n setLoggedHidden(true);\n return;\n }\n setCurrentTime(initialTime);\n setInitialized(true);\n setLoggedHidden(false); \n }, [sessionManager, connectionBroken]);\n\n React.useEffect(() => {\n if (connectionBroken) {\n if (!loggedHidden) {\n setLoggedHidden(true);\n }\n return;\n }\n \n if (timeLeft && timeLeft > 0) {\n setCurrentTime(timeLeft);\n }\n setLoggedHidden(false);\n }, [timeLeft, connectionBroken]);\n\n React.useEffect(() => {\n if (!initialized) {\n return;\n }\n\n if (connectionBroken) {\n if (!loggedHidden) {\n setLoggedHidden(true);\n }\n return;\n }\n\n if (!currentTime || currentTime <= 0 || !sessionManager) {\n return;\n }\n\n const interval = setInterval(() => {\n if (connectionBroken) {\n setCurrentTime(0);\n clearInterval(interval);\n return;\n }\n \n if (sessionManager?.hasActiveSession()) {\n const newTime = sessionManager.getTimeLeft();\n setCurrentTime(newTime);\n\n if (window.DEBUG_MODE && Math.floor(Date.now() / 30000) !== Math.floor((Date.now() - 1000) / 30000)) {\n console.log('\u23F1\uFE0F Timer tick:', Math.floor(newTime / 1000) + 's');\n }\n\n if (newTime <= 0) {\n setShowExpiredMessage(true);\n setTimeout(() => setShowExpiredMessage(false), 5000);\n clearInterval(interval);\n }\n } else {\n setCurrentTime(0);\n clearInterval(interval);\n }\n }, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, [initialized, currentTime, sessionManager, connectionBroken]);\n\n React.useEffect(() => {\n const handleSessionTimerUpdate = (event) => {\n if (connectionBroken) {\n return;\n }\n \n if (event.detail.timeLeft && event.detail.timeLeft > 0) {\n setCurrentTime(event.detail.timeLeft);\n }\n };\n\n const handleForceHeaderUpdate = (event) => {\n if (connectionBroken) {\n return;\n }\n \n if (sessionManager && sessionManager.hasActiveSession()) {\n const newTime = sessionManager.getTimeLeft();\n setCurrentTime(newTime);\n } else {\n setCurrentTime(event.detail.timeLeft);\n }\n };\n\n const handlePeerDisconnect = (event) => {\n setConnectionBroken(true);\n setCurrentTime(0);\n setShowExpiredMessage(false);\n setLoggedHidden(false);\n };\n\n const handleNewConnection = (event) => {\n setConnectionBroken(false);\n setLoggedHidden(false); \n };\n\n const handleConnectionCleaned = (event) => {\n setConnectionBroken(true);\n setCurrentTime(0);\n setShowExpiredMessage(false);\n setInitialized(false);\n setLoggedHidden(false);\n };\n\n const handleSessionReset = (event) => {\n setConnectionBroken(true);\n setCurrentTime(0);\n setShowExpiredMessage(false);\n setInitialized(false);\n setLoggedHidden(false);\n };\n\n const handleSessionCleanup = (event) => {\n setConnectionBroken(true);\n setCurrentTime(0);\n setShowExpiredMessage(false);\n setInitialized(false);\n setLoggedHidden(false);\n };\n\n const handleDisconnected = (event) => {\n setConnectionBroken(true);\n setCurrentTime(0);\n setShowExpiredMessage(false);\n setInitialized(false);\n setLoggedHidden(false);\n };\n\n document.addEventListener('session-timer-update', handleSessionTimerUpdate);\n document.addEventListener('force-header-update', handleForceHeaderUpdate);\n document.addEventListener('peer-disconnect', handlePeerDisconnect);\n document.addEventListener('new-connection', handleNewConnection);\n document.addEventListener('connection-cleaned', handleConnectionCleaned);\n document.addEventListener('session-reset', handleSessionReset);\n document.addEventListener('session-cleanup', handleSessionCleanup);\n document.addEventListener('disconnected', handleDisconnected);\n\n return () => {\n document.removeEventListener('session-timer-update', handleSessionTimerUpdate);\n document.removeEventListener('force-header-update', handleForceHeaderUpdate);\n document.removeEventListener('peer-disconnect', handlePeerDisconnect);\n document.removeEventListener('new-connection', handleNewConnection);\n document.removeEventListener('connection-cleaned', handleConnectionCleaned);\n document.removeEventListener('session-reset', handleSessionReset);\n document.removeEventListener('session-cleanup', handleSessionCleanup);\n document.removeEventListener('disconnected', handleDisconnected);\n };\n }, [sessionManager]);\n\n if (showExpiredMessage) {\n return React.createElement('div', {\n className: 'session-timer expired flex items-center space-x-2 px-3 py-1.5 rounded-lg animate-pulse',\n style: { background: 'linear-gradient(135deg, rgba(239, 68, 68, 0.2) 0%, rgba(220, 38, 38, 0.2) 100%)' }\n }, [\n React.createElement('i', {\n key: 'icon',\n className: 'fas fa-exclamation-triangle text-red-400'\n }),\n React.createElement('span', {\n key: 'message',\n className: 'text-red-400 text-sm font-medium'\n }, 'Session Expired!')\n ]);\n }\n\n if (!sessionManager) {\n if (!loggedHidden) {\n console.log('\u23F1\uFE0F SessionTimer hidden - no sessionManager');\n setLoggedHidden(true);\n }\n return null;\n }\n\n if (connectionBroken) {\n if (!loggedHidden) {\n console.log('\u23F1\uFE0F SessionTimer hidden - connection broken');\n setLoggedHidden(true);\n }\n return null;\n }\n\n if (!currentTime || currentTime <= 0) {\n if (!loggedHidden) {\n console.log('\u23F1\uFE0F SessionTimer hidden - no time left, currentTime:', currentTime);\n setLoggedHidden(true);\n }\n return null;\n }\n\n if (loggedHidden) {\n setLoggedHidden(false);\n }\n\n const totalMinutes = Math.floor(currentTime / (60 * 1000));\n const totalSeconds = Math.floor(currentTime / 1000);\n \n const isDemo = sessionType === 'demo';\n const isWarning = isDemo ? totalMinutes <= 2 : totalMinutes <= 10;\n const isCritical = isDemo ? totalSeconds <= 60 : totalMinutes <= 5;\n\n const formatTime = (ms) => {\n const hours = Math.floor(ms / (60 * 60 * 1000));\n const minutes = Math.floor((ms % (60 * 60 * 1000)) / (60 * 1000));\n const seconds = Math.floor((ms % (60 * 1000)) / 1000);\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;\n } else {\n return `${minutes}:${seconds.toString().padStart(2, '0')}`;\n }\n };\n\n const getTimerStyle = () => {\n const totalDuration = sessionType === 'demo' ? 6 * 60 * 1000 : 60 * 60 * 1000;\n const timeProgress = (totalDuration - currentTime) / totalDuration;\n \n let backgroundColor, textColor, iconColor, iconClass, shouldPulse;\n \n if (timeProgress <= 0.33) {\n backgroundColor = 'linear-gradient(135deg, rgba(34, 197, 94, 0.15) 0%, rgba(22, 163, 74, 0.15) 100%)';\n textColor = 'text-green-400';\n iconColor = 'text-green-400';\n iconClass = 'fas fa-clock';\n shouldPulse = false;\n } else if (timeProgress <= 0.66) {\n backgroundColor = 'linear-gradient(135deg, rgba(234, 179, 8, 0.15) 0%, rgba(202, 138, 4, 0.15) 100%)';\n textColor = 'text-yellow-400';\n iconColor = 'text-yellow-400';\n iconClass = 'fas fa-clock';\n shouldPulse = false;\n } else {\n backgroundColor = 'linear-gradient(135deg, rgba(239, 68, 68, 0.15) 0%, rgba(220, 38, 38, 0.15) 100%)';\n textColor = 'text-red-400';\n iconColor = 'text-red-400';\n iconClass = 'fas fa-exclamation-triangle';\n shouldPulse = true;\n }\n \n return { backgroundColor, textColor, iconColor, iconClass, shouldPulse };\n };\n\n const timerStyle = getTimerStyle();\n \n const handleTimerClick = () => {\n if (onDisconnect && typeof onDisconnect === 'function') {\n onDisconnect();\n }\n };\n\n return React.createElement('div', {\n className: `session-timer flex items-center space-x-2 px-3 py-1.5 rounded-lg transition-all duration-500 cursor-pointer hover:opacity-80 ${\n isDemo ? 'demo-session' : ''\n } ${timerStyle.shouldPulse ? 'animate-pulse' : ''}`,\n style: { background: timerStyle.backgroundColor },\n onClick: handleTimerClick,\n title: 'Click to disconnect and clear session'\n }, [\n React.createElement('i', {\n key: 'icon',\n className: `${timerStyle.iconClass} ${timerStyle.iconColor}`\n }),\n React.createElement('span', {\n key: 'time',\n className: `text-sm font-mono font-semibold ${timerStyle.textColor}`\n }, formatTime(currentTime)),\n React.createElement('div', {\n key: 'progress',\n className: 'ml-2 w-16 h-1 bg-gray-700 rounded-full overflow-hidden'\n }, [\n React.createElement('div', {\n key: 'progress-bar',\n className: `${timerStyle.textColor.replace('text-', 'bg-')} h-full rounded-full transition-all duration-500`,\n style: { \n width: `${Math.max(0, Math.min(100, (currentTime / (sessionType === 'demo' ? 6 * 60 * 1000 : 60 * 60 * 1000)) * 100))}%`\n }\n })\n ])\n ]);\n};\n\nwindow.SessionTimer = SessionTimer;\n\nwindow.updateSessionTimer = (newTimeLeft, newSessionType) => {\n document.dispatchEvent(new CustomEvent('session-timer-update', {\n detail: { timeLeft: newTimeLeft, sessionType: newSessionType }\n }));\n};\n\n", "const EnhancedMinimalHeader = ({ \n status, \n fingerprint, \n verificationCode, \n onDisconnect, \n isConnected, \n securityLevel, \n sessionManager, \n sessionTimeLeft,\n webrtcManager \n}) => {\n const [currentTimeLeft, setCurrentTimeLeft] = React.useState(sessionTimeLeft || 0);\n const [hasActiveSession, setHasActiveSession] = React.useState(false);\n const [sessionType, setSessionType] = React.useState('unknown');\n const [realSecurityLevel, setRealSecurityLevel] = React.useState(null);\n const [lastSecurityUpdate, setLastSecurityUpdate] = React.useState(0);\n\n // ============================================\n // FIXED SECURITY UPDATE LOGIC\n // ============================================\n \n React.useEffect(() => {\n let isUpdating = false; \n let lastUpdateAttempt = 0; \n \n const updateRealSecurityStatus = async () => {\n const now = Date.now();\n if (now - lastUpdateAttempt < 10000) { \n return;\n }\n\n if (isUpdating) {\n return;\n }\n \n isUpdating = true;\n lastUpdateAttempt = now;\n \n try {\n if (!webrtcManager || !isConnected) {\n return;\n }\n \n const activeWebrtcManager = webrtcManager;\n \n let realSecurityData = null;\n \n if (typeof activeWebrtcManager.getRealSecurityLevel === 'function') {\n realSecurityData = await activeWebrtcManager.getRealSecurityLevel();\n } else if (typeof activeWebrtcManager.calculateAndReportSecurityLevel === 'function') {\n realSecurityData = await activeWebrtcManager.calculateAndReportSecurityLevel();\n } else {\n realSecurityData = await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(activeWebrtcManager);\n }\n \n if (window.DEBUG_MODE) {\n console.log('\uD83D\uDD10 REAL security level calculated:', {\n level: realSecurityData?.level,\n score: realSecurityData?.score,\n passedChecks: realSecurityData?.passedChecks,\n totalChecks: realSecurityData?.totalChecks,\n isRealData: realSecurityData?.isRealData,\n sessionType: realSecurityData?.sessionType,\n maxPossibleScore: realSecurityData?.maxPossibleScore,\n verificationResults: realSecurityData?.verificationResults ? Object.keys(realSecurityData.verificationResults) : []\n });\n }\n \n if (realSecurityData && realSecurityData.isRealData !== false) {\n const currentScore = realSecurityLevel?.score || 0;\n const newScore = realSecurityData.score || 0;\n\n if (currentScore !== newScore || !realSecurityLevel) {\n setRealSecurityLevel(realSecurityData);\n setLastSecurityUpdate(now);\n \n if (window.DEBUG_MODE) {\n console.log('\u2705 Security level updated in header component:', {\n oldScore: currentScore,\n newScore: newScore,\n sessionType: realSecurityData.sessionType\n });\n }\n } else if (window.DEBUG_MODE) {\n console.log('\u2139\uFE0F Security level unchanged, skipping update');\n }\n } else {\n console.warn('\u26A0\uFE0F Security calculation returned invalid data');\n }\n \n } catch (error) {\n console.error('\u274C Error in real security calculation:', error);\n } finally {\n isUpdating = false;\n }\n };\n\n if (isConnected) {\n updateRealSecurityStatus();\n \n if (!realSecurityLevel || realSecurityLevel.score < 50) {\n const retryInterval = setInterval(() => {\n if (!realSecurityLevel || realSecurityLevel.score < 50) {\n updateRealSecurityStatus();\n } else {\n clearInterval(retryInterval);\n }\n }, 5000); \n \n setTimeout(() => clearInterval(retryInterval), 30000);\n }\n }\n\n const interval = setInterval(updateRealSecurityStatus, 30000);\n \n return () => clearInterval(interval);\n }, [webrtcManager, isConnected, lastSecurityUpdate, realSecurityLevel]);\n\n // ============================================\n // FIXED EVENT HANDLERS\n // ============================================\n\n React.useEffect(() => {\n const handleSecurityUpdate = (event) => {\n if (window.DEBUG_MODE) {\n console.log('\uD83D\uDD12 Security level update event received:', event.detail);\n }\n\n setTimeout(() => {\n setLastSecurityUpdate(0);\n }, 100);\n };\n\n const handleRealSecurityCalculated = (event) => {\n if (window.DEBUG_MODE) {\n console.log('\uD83D\uDD10 Real security calculated event:', event.detail);\n }\n \n if (event.detail && event.detail.securityData) {\n setRealSecurityLevel(event.detail.securityData);\n setLastSecurityUpdate(Date.now());\n }\n };\n\n document.addEventListener('security-level-updated', handleSecurityUpdate);\n document.addEventListener('real-security-calculated', handleRealSecurityCalculated);\n \n window.forceHeaderSecurityUpdate = (webrtcManager) => {\n if (window.DEBUG_MODE) {\n console.log('\uD83D\uDD04 Force header security update called');\n }\n \n if (webrtcManager && window.EnhancedSecureCryptoUtils) {\n window.EnhancedSecureCryptoUtils.calculateSecurityLevel(webrtcManager)\n .then(securityData => {\n if (securityData && securityData.isRealData !== false) {\n setRealSecurityLevel(securityData);\n setLastSecurityUpdate(Date.now());\n console.log('\u2705 Header security level force-updated');\n }\n })\n .catch(error => {\n console.error('\u274C Force update failed:', error);\n });\n } else {\n setLastSecurityUpdate(0); \n }\n };\n\n return () => {\n document.removeEventListener('security-level-updated', handleSecurityUpdate);\n document.removeEventListener('real-security-calculated', handleRealSecurityCalculated);\n };\n }, []);\n\n // ============================================\n // REST of the component logic\n // ============================================\n\n React.useEffect(() => {\n const updateSessionInfo = () => {\n if (sessionManager) {\n const isActive = sessionManager.hasActiveSession();\n const timeLeft = sessionManager.getTimeLeft();\n const currentSession = sessionManager.currentSession;\n \n setHasActiveSession(isActive);\n setCurrentTimeLeft(timeLeft);\n setSessionType(currentSession?.type || 'unknown');\n }\n };\n\n updateSessionInfo();\n const interval = setInterval(updateSessionInfo, 1000);\n return () => clearInterval(interval);\n }, [sessionManager]);\n\n React.useEffect(() => {\n if (sessionManager?.hasActiveSession()) {\n setCurrentTimeLeft(sessionManager.getTimeLeft());\n setHasActiveSession(true);\n } else {\n setHasActiveSession(false);\n setRealSecurityLevel(null);\n setLastSecurityUpdate(0);\n setSessionType('unknown');\n }\n }, [sessionManager, sessionTimeLeft]);\n\n React.useEffect(() => {\n const handleForceUpdate = (event) => {\n if (sessionManager) {\n const isActive = sessionManager.hasActiveSession();\n const timeLeft = sessionManager.getTimeLeft();\n const currentSession = sessionManager.currentSession;\n \n setHasActiveSession(isActive);\n setCurrentTimeLeft(timeLeft);\n setSessionType(currentSession?.type || 'unknown');\n }\n };\n\n // Connection cleanup handler (use existing event from module)\n const handleConnectionCleaned = () => {\n if (window.DEBUG_MODE) {\n console.log('\uD83E\uDDF9 Connection cleaned - clearing security data in header');\n }\n\n setRealSecurityLevel(null);\n setLastSecurityUpdate(0);\n\n setHasActiveSession(false);\n setCurrentTimeLeft(0);\n setSessionType('unknown');\n };\n\n const handlePeerDisconnect = () => {\n if (window.DEBUG_MODE) {\n console.log('\uD83D\uDC4B Peer disconnect detected - clearing security data in header');\n }\n\n setRealSecurityLevel(null);\n setLastSecurityUpdate(0);\n };\n\n document.addEventListener('force-header-update', handleForceUpdate);\n document.addEventListener('peer-disconnect', handlePeerDisconnect);\n document.addEventListener('connection-cleaned', handleConnectionCleaned);\n \n return () => {\n document.removeEventListener('force-header-update', handleForceUpdate);\n document.removeEventListener('peer-disconnect', handlePeerDisconnect);\n document.removeEventListener('connection-cleaned', handleConnectionCleaned);\n };\n }, [sessionManager]);\n\n // ============================================\n // SECURITY INDICATOR CLICK HANDLER\n // ============================================\n\n const handleSecurityClick = (event) => {\n // Check if it's a right-click or Ctrl+click to disconnect\n if (event && (event.button === 2 || event.ctrlKey || event.metaKey)) {\n if (onDisconnect && typeof onDisconnect === 'function') {\n onDisconnect();\n return;\n }\n }\n\n if (!realSecurityLevel) {\n alert('Security verification in progress...\\nPlease wait for real-time cryptographic verification to complete.');\n return;\n }\n\n // Detailed information about the REAL security check\n let message = `\uD83D\uDD12 REAL-TIME SECURITY VERIFICATION\\n\\n`;\n message += `Security Level: ${realSecurityLevel.level} (${realSecurityLevel.score}%)\\n`;\n message += `Session Type: ${realSecurityLevel.sessionType || 'demo'}\\n`;\n message += `Verification Time: ${new Date(realSecurityLevel.timestamp).toLocaleTimeString()}\\n`;\n message += `Data Source: ${realSecurityLevel.isRealData ? 'Real Cryptographic Tests' : 'Simulated Data'}\\n\\n`;\n \n if (realSecurityLevel.verificationResults) {\n message += 'DETAILED CRYPTOGRAPHIC TESTS:\\n';\n message += '=' + '='.repeat(40) + '\\n';\n \n const passedTests = Object.entries(realSecurityLevel.verificationResults).filter(([key, result]) => result.passed);\n const failedTests = Object.entries(realSecurityLevel.verificationResults).filter(([key, result]) => !result.passed);\n \n if (passedTests.length > 0) {\n message += '\u2705 PASSED TESTS:\\n';\n passedTests.forEach(([key, result]) => {\n const testName = key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());\n message += ` ${testName}: ${result.details}\\n`;\n });\n message += '\\n';\n }\n \n if (failedTests.length > 0) {\n message += '\u274C UNAVAILABLE/Failed TESTS:\\n';\n failedTests.forEach(([key, result]) => {\n const testName = key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());\n message += ` ${testName}: ${result.details}\\n`;\n });\n message += '\\n';\n }\n \n message += `SUMMARY:\\n`;\n message += `Passed: ${realSecurityLevel.passedChecks}/${realSecurityLevel.totalChecks} tests\\n`;\n }\n \n // Add information about what is available in other sessions\n message += `\\n\uD83D\uDCCB WHAT'S AVAILABLE IN OTHER SESSIONS:\\n`;\n message += '=' + '='.repeat(40) + '\\n';\n \n if (realSecurityLevel.sessionType === 'demo') {\n message += `\uD83D\uDD12 BASIC SESSION (5,000 sat - $2.00):\\n`;\n message += ` \u2022 ECDSA Digital Signatures\\n`;\n message += ` \u2022 Metadata Protection\\n`;\n message += ` \u2022 Perfect Forward Secrecy\\n`;\n message += ` \u2022 Nested Encryption\\n`;\n message += ` \u2022 Packet Padding\\n\\n`;\n \n message += `\uD83D\uDE80 PREMIUM SESSION (20,000 sat - $8.00):\\n`;\n message += ` \u2022 All Basic + Enhanced features\\n`;\n message += ` \u2022 Traffic Obfuscation\\n`;\n message += ` \u2022 Fake Traffic Generation\\n`;\n message += ` \u2022 Decoy Channels\\n`;\n message += ` \u2022 Anti-Fingerprinting\\n`;\n message += ` \u2022 Message Chunking\\n`;\n message += ` \u2022 Advanced Replay Protection\\n`;\n } else if (realSecurityLevel.sessionType === 'basic') {\n message += `\uD83D\uDE80 PREMIUM SESSION (20,000 sat - $8.00):\\n`;\n message += ` \u2022 Traffic Obfuscation\\n`;\n message += ` \u2022 Fake Traffic Generation\\n`;\n message += ` \u2022 Decoy Channels\\n`;\n message += ` \u2022 Anti-Fingerprinting\\n`;\n message += ` \u2022 Message Chunking\\n`;\n message += ` \u2022 Advanced Replay Protection\\n`;\n }\n \n message += `\\n${realSecurityLevel.details || 'Real cryptographic verification completed'}`;\n \n if (realSecurityLevel.isRealData) {\n message += '\\n\\n\u2705 This is REAL-TIME verification using actual cryptographic functions.';\n } else {\n message += '\\n\\n\u26A0\uFE0F Warning: This data may be simulated. Connection may not be fully established.';\n }\n \n alert(message);\n };\n\n // ============================================\n // DISPLAY UTILITIES\n // ============================================\n\n const getStatusConfig = () => {\n switch (status) {\n case 'connected':\n return {\n text: 'Connected',\n className: 'status-connected',\n badgeClass: 'bg-green-500/10 text-green-400 border-green-500/20'\n };\n case 'verifying':\n return {\n text: 'Verifying...',\n className: 'status-verifying',\n badgeClass: 'bg-purple-500/10 text-purple-400 border-purple-500/20'\n };\n case 'connecting':\n return {\n text: 'Connecting...',\n className: 'status-connecting',\n badgeClass: 'bg-blue-500/10 text-blue-400 border-blue-500/20'\n };\n case 'retrying':\n return {\n text: 'Retrying...',\n className: 'status-connecting',\n badgeClass: 'bg-yellow-500/10 text-yellow-400 border-yellow-500/20'\n };\n case 'failed':\n return {\n text: 'Error',\n className: 'status-failed',\n badgeClass: 'bg-red-500/10 text-red-400 border-red-500/20'\n };\n case 'reconnecting':\n return {\n text: 'Reconnecting...',\n className: 'status-connecting',\n badgeClass: 'bg-yellow-500/10 text-yellow-400 border-yellow-500/20'\n };\n case 'peer_disconnected':\n return {\n text: 'Peer disconnected',\n className: 'status-failed',\n badgeClass: 'bg-orange-500/10 text-orange-400 border-orange-500/20'\n };\n default:\n return {\n text: 'Not connected',\n className: 'status-disconnected',\n badgeClass: 'bg-gray-500/10 text-gray-400 border-gray-500/20'\n };\n }\n };\n\n const config = getStatusConfig();\n const displaySecurityLevel = realSecurityLevel || securityLevel;\n \n const shouldShowTimer = hasActiveSession && currentTimeLeft > 0 && window.SessionTimer;\n\n // ============================================\n // DATA RELIABILITY INDICATOR\n // ============================================\n\n const getSecurityIndicatorDetails = () => {\n if (!displaySecurityLevel) {\n return {\n tooltip: 'Security verification in progress...',\n isVerified: false,\n dataSource: 'loading'\n };\n }\n \n const isRealData = displaySecurityLevel.isRealData !== false;\n const baseTooltip = `${displaySecurityLevel.level} (${displaySecurityLevel.score}%)`;\n \n if (isRealData) {\n return {\n tooltip: `${baseTooltip} - Real-time verification \u2705\\nRight-click or Ctrl+click to disconnect`,\n isVerified: true,\n dataSource: 'real'\n };\n } else {\n return {\n tooltip: `${baseTooltip} - Estimated (connection establishing...)\\nRight-click or Ctrl+click to disconnect`,\n isVerified: false,\n dataSource: 'estimated'\n };\n }\n };\n\n const securityDetails = getSecurityIndicatorDetails();\n\n // ============================================\n // ADDING global methods for debugging\n // ============================================\n\n React.useEffect(() => {\n window.debugHeaderSecurity = () => {\n console.log('\uD83D\uDD0D Header Security Debug:', {\n realSecurityLevel,\n lastSecurityUpdate,\n isConnected,\n webrtcManagerProp: !!webrtcManager,\n windowWebrtcManager: !!window.webrtcManager,\n cryptoUtils: !!window.EnhancedSecureCryptoUtils,\n displaySecurityLevel: displaySecurityLevel,\n securityDetails: securityDetails\n });\n };\n \n return () => {\n delete window.debugHeaderSecurity;\n };\n }, [realSecurityLevel, lastSecurityUpdate, isConnected, webrtcManager, displaySecurityLevel, securityDetails]);\n\n // ============================================\n // RENDER\n // ============================================\n\n return React.createElement('header', {\n className: 'header-minimal sticky top-0 z-50'\n }, [\n React.createElement('div', {\n key: 'container',\n className: 'max-w-7xl mx-auto px-4 sm:px-6 lg:px-8'\n }, [\n React.createElement('div', {\n key: 'content',\n className: 'flex items-center justify-between h-16'\n }, [\n // Logo and Title\n React.createElement('div', {\n key: 'logo-section',\n className: 'flex items-center space-x-2 sm:space-x-3'\n }, [\n React.createElement('div', {\n key: 'logo',\n className: 'icon-container w-8 h-8 sm:w-10 sm:h-10'\n }, [\n React.createElement('i', {\n className: 'fas fa-shield-halved accent-orange text-sm sm:text-base'\n })\n ]),\n React.createElement('div', {\n key: 'title-section'\n }, [\n React.createElement('h1', {\n key: 'title',\n className: 'text-lg sm:text-xl font-semibold text-primary'\n }, 'SecureBit.chat'),\n React.createElement('p', {\n key: 'subtitle',\n className: 'text-xs sm:text-sm text-muted hidden sm:block'\n }, 'End-to-end freedom v4.02.985')\n ])\n ]),\n\n // Status and Controls - Responsive\n React.createElement('div', {\n key: 'status-section',\n className: 'flex items-center space-x-2 sm:space-x-3'\n }, [\n // Session Timer\n shouldShowTimer && React.createElement(window.SessionTimer, {\n key: 'session-timer',\n timeLeft: currentTimeLeft,\n sessionType: sessionType,\n sessionManager: sessionManager,\n onDisconnect: onDisconnect\n }),\n\n displaySecurityLevel && React.createElement('div', {\n key: 'security-level',\n className: 'hidden md:flex items-center space-x-2 cursor-pointer hover:opacity-80 transition-opacity duration-200',\n onClick: handleSecurityClick,\n onContextMenu: (e) => {\n e.preventDefault();\n if (onDisconnect && typeof onDisconnect === 'function') {\n onDisconnect();\n }\n },\n title: securityDetails.tooltip\n }, [\n React.createElement('div', {\n key: 'security-icon',\n className: `w-6 h-6 rounded-full flex items-center justify-center relative ${\n displaySecurityLevel.color === 'green' ? 'bg-green-500/20' :\n displaySecurityLevel.color === 'orange' ? 'bg-orange-500/20' :\n displaySecurityLevel.color === 'yellow' ? 'bg-yellow-500/20' : 'bg-red-500/20'\n } ${securityDetails.isVerified ? '' : 'animate-pulse'}`\n }, [\n React.createElement('i', {\n className: `fas fa-shield-alt text-xs ${\n displaySecurityLevel.color === 'green' ? 'text-green-400' :\n displaySecurityLevel.color === 'orange' ? 'text-orange-400' :\n displaySecurityLevel.color === 'yellow' ? 'text-yellow-400' : 'text-red-400'\n }`\n })\n ]),\n React.createElement('div', {\n key: 'security-info',\n className: 'flex flex-col'\n }, [\n React.createElement('div', {\n key: 'security-level-text',\n className: 'text-xs font-medium text-primary flex items-center space-x-1'\n }, [\n React.createElement('span', {}, `${displaySecurityLevel.level} (${displaySecurityLevel.score}%)`)\n ]),\n React.createElement('div', {\n key: 'security-details',\n className: 'text-xs text-muted mt-1 hidden lg:block'\n }, securityDetails.dataSource === 'real' ? \n `${displaySecurityLevel.passedChecks || 0}/${displaySecurityLevel.totalChecks || 0} tests` :\n (displaySecurityLevel.details || `Stage ${displaySecurityLevel.stage || 1}`)\n ),\n React.createElement('div', {\n key: 'security-progress',\n className: 'w-16 h-1 bg-gray-600 rounded-full overflow-hidden'\n }, [\n React.createElement('div', {\n key: 'progress-bar',\n className: `h-full transition-all duration-500 ${\n displaySecurityLevel.color === 'green' ? 'bg-green-400' :\n displaySecurityLevel.color === 'orange' ? 'bg-orange-400' :\n displaySecurityLevel.color === 'yellow' ? 'bg-yellow-400' : 'bg-red-400'\n }`,\n style: { width: `${displaySecurityLevel.score}%` }\n })\n ])\n ])\n ]),\n\n // Mobile Security Indicator\n displaySecurityLevel && React.createElement('div', {\n key: 'mobile-security',\n className: 'md:hidden flex items-center'\n }, [\n React.createElement('div', {\n key: 'mobile-security-icon',\n className: `w-8 h-8 rounded-full flex items-center justify-center cursor-pointer hover:opacity-80 transition-opacity duration-200 relative ${\n displaySecurityLevel.color === 'green' ? 'bg-green-500/20' :\n displaySecurityLevel.color === 'orange' ? 'bg-orange-500/20' :\n displaySecurityLevel.color === 'yellow' ? 'bg-yellow-500/20' : 'bg-red-500/20'\n } ${securityDetails.isVerified ? '' : 'animate-pulse'}`,\n title: securityDetails.tooltip,\n onClick: handleSecurityClick,\n onContextMenu: (e) => {\n e.preventDefault();\n if (onDisconnect && typeof onDisconnect === 'function') {\n onDisconnect();\n }\n }\n }, [\n React.createElement('i', {\n className: `fas fa-shield-alt text-sm ${\n displaySecurityLevel.color === 'green' ? 'text-green-400' :\n displaySecurityLevel.color === 'orange' ? 'text-orange-400' :\n displaySecurityLevel.color === 'yellow' ? 'text-yellow-400' : 'text-red-400'\n }`\n })\n ])\n ]),\n\n // Status Badge\n React.createElement('div', {\n key: 'status-badge',\n className: `px-2 sm:px-3 py-1.5 rounded-lg border ${config.badgeClass} flex items-center space-x-1 sm:space-x-2`\n }, [\n React.createElement('span', {\n key: 'status-dot',\n className: `status-dot ${config.className}`\n }),\n React.createElement('span', {\n key: 'status-text',\n className: 'text-xs sm:text-sm font-medium'\n }, config.text)\n ]),\n\n // Disconnect Button\n isConnected && React.createElement('button', {\n key: 'disconnect-btn',\n onClick: onDisconnect,\n className: 'p-1.5 sm:px-3 sm:py-1.5 bg-red-500/10 hover:bg-red-500/20 text-red-400 border border-red-500/20 rounded-lg transition-all duration-200 text-sm'\n }, [\n React.createElement('i', {\n className: 'fas fa-power-off sm:mr-2'\n }),\n React.createElement('span', {\n className: 'hidden sm:inline'\n }, 'Disconnect')\n ])\n ])\n ])\n ])\n ]);\n};\n\nwindow.EnhancedMinimalHeader = EnhancedMinimalHeader;\n", "const SessionTypeSelector = ({ onSelectType, onCancel, sessionManager }) => {\n const [selectedType, setSelectedType] = React.useState(null);\n const [demoInfo, setDemoInfo] = React.useState(null);\n const [refreshTimer, setRefreshTimer] = React.useState(null);\n const [lastRefresh, setLastRefresh] = React.useState(Date.now());\n\n // We receive up-to-date information about demo limits\n const updateDemoInfo = React.useCallback(() => {\n if (sessionManager && sessionManager.getDemoSessionInfo) {\n try {\n const info = sessionManager.getDemoSessionInfo();\n if (window.DEBUG_MODE) {\n console.log('\uD83D\uDD04 Demo info updated:', info);\n }\n setDemoInfo(info);\n setLastRefresh(Date.now());\n } catch (error) {\n console.error('Failed to get demo info:', error);\n }\n }\n }, [sessionManager]);\n\n // Update information on load and every 10 seconds\n React.useEffect(() => {\n updateDemoInfo();\n const interval = setInterval(updateDemoInfo, 10000); \n setRefreshTimer(interval);\n return () => {\n if (interval) clearInterval(interval);\n };\n }, [updateDemoInfo]);\n\n // Clear timer on unmount\n React.useEffect(() => {\n return () => {\n if (refreshTimer) {\n clearInterval(refreshTimer);\n }\n };\n }, [refreshTimer]);\n\n const sessionTypes = [\n { \n id: 'demo', \n name: 'Demo', \n duration: '6 minutes', \n price: '0 sat', \n usd: '$0.00', \n popular: false,\n securityLevel: 'Basic',\n securityBadge: 'BASIC',\n securityColor: 'bg-blue-500/20 text-blue-300',\n description: 'Limited testing session with basic security',\n features: [\n 'Basic end-to-end encryption', \n 'Simple key exchange', \n 'Message integrity',\n 'Rate limiting'\n ],\n limitations: [\n 'No advanced security features',\n 'No traffic obfuscation',\n 'No metadata protection'\n ]\n },\n { \n id: 'basic', \n name: 'Basic', \n duration: '1 hour', \n price: '5,000 sat', \n usd: '$2.00',\n securityLevel: 'Enhanced',\n securityBadge: 'ENHANCED',\n securityColor: 'bg-orange-500/20 text-orange-300',\n popular: true,\n description: 'Full featured session with enhanced security',\n features: [\n 'All basic features',\n 'ECDSA digital signatures', \n 'Metadata protection', \n 'Perfect forward secrecy',\n 'Nested encryption',\n 'Packet padding',\n 'Complete ASN.1 validation',\n 'OID and EC point verification',\n 'SPKI structure validation',\n '18-layer security architecture',\n 'ASN.1 Validated'\n ],\n limitations: [\n 'Limited traffic obfuscation',\n 'No fake traffic generation'\n ]\n },\n { \n id: 'premium', \n name: 'Premium', \n duration: '6 hours', \n price: '20,000 sat', \n usd: '$8.00',\n securityLevel: 'Maximum',\n securityBadge: 'MAXIMUM',\n securityColor: 'bg-green-500/20 text-green-300',\n description: 'Extended session with maximum security protection',\n features: [\n 'All enhanced features',\n 'Traffic obfuscation', \n 'Fake traffic generation',\n 'Decoy channels',\n 'Anti-fingerprinting',\n 'Message chunking',\n 'Advanced replay protection',\n 'Complete ASN.1 validation',\n 'OID and EC point verification',\n 'SPKI structure validation',\n '18-layer security architecture',\n 'ASN.1 Validated'\n ],\n limitations: []\n }\n ];\n\n const handleTypeSelect = (typeId) => {\n console.log(`\uD83C\uDFAF Selecting session type: ${typeId}`);\n \n if (typeId === 'demo') {\n if (demoInfo && !demoInfo.canUseNow) {\n let message = `Demo session not available.\\n\\n`;\n \n if (demoInfo.blockingReason === 'global_limit') {\n message += `Reason: Too many global demo sessions active (${demoInfo.globalActive}/${demoInfo.globalLimit})\\n`;\n message += `Please try again in a few minutes.`;\n } else if (demoInfo.blockingReason === 'daily_limit') {\n message += `Reason: Daily limit reached (${demoInfo.used}/${demoInfo.total})\\n`;\n message += `Next available: ${demoInfo.nextAvailable}`;\n } else if (demoInfo.blockingReason === 'session_cooldown') {\n message += `Reason: Cooldown between sessions\\n`;\n message += `Next available: ${demoInfo.nextAvailable}`;\n } else if (demoInfo.blockingReason === 'completion_cooldown') {\n message += `Reason: Wait period after last session\\n`;\n message += `Next available: ${demoInfo.nextAvailable}`;\n } else {\n message += `Next available: ${demoInfo.nextAvailable}`;\n }\n \n alert(message);\n return;\n }\n }\n setSelectedType(typeId);\n };\n\n const formatCooldownTime = (minutes) => {\n if (minutes >= 60) {\n const hours = Math.floor(minutes / 60);\n const remainingMinutes = minutes % 60;\n return `${hours}h ${remainingMinutes}m`;\n }\n return `${minutes}m`;\n };\n\n return React.createElement('div', { className: 'space-y-6' }, [\n React.createElement('div', { key: 'header', className: 'text-center' }, [\n React.createElement('h3', { \n key: 'title', \n className: 'text-xl font-semibold text-white mb-2' \n }, 'Choose Your Session'),\n React.createElement('p', { \n key: 'subtitle', \n className: 'text-gray-300 text-sm' \n }, 'Different security levels for different needs')\n ]),\n \n React.createElement('div', { key: 'types', className: 'space-y-4' }, \n sessionTypes.map(type => {\n const isDemo = type.id === 'demo';\n const isDisabled = isDemo && demoInfo && !demoInfo.canUseNow;\n \n return React.createElement('div', {\n key: type.id,\n onClick: () => !isDisabled && handleTypeSelect(type.id),\n className: `relative card-minimal ${selectedType === type.id ? 'card-minimal--selected' : ''} rounded-lg p-5 border-2 transition-all ${\n selectedType === type.id\n ? 'border-orange-500 bg-orange-500/15 ring-2 ring-orange-400 ring-offset-2 ring-offset-black/30'\n : 'border-gray-600 hover:border-orange-400'\n } ${type.popular && selectedType !== type.id ? 'ring-2 ring-orange-500/30' : ''} ${\n isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'\n }`\n }, [\n // Popular badge\n type.popular && React.createElement('div', { \n key: 'popular-badge', \n className: 'absolute -top-2 right-3 bg-orange-500 text-white text-xs px-3 py-1 rounded-full font-medium' \n }, 'Most Popular'),\n \n React.createElement('div', { key: 'content', className: 'space-y-4' }, [\n // Header with name and security level\n React.createElement('div', { key: 'header', className: 'flex items-start justify-between' }, [\n React.createElement('div', { key: 'title-section' }, [\n React.createElement('div', { key: 'name-row', className: 'flex items-center gap-3 mb-2' }, [\n React.createElement('h4', { \n key: 'name', \n className: 'text-xl font-bold text-white' \n }, type.name),\n isDemo && React.createElement('span', {\n key: 'free-badge',\n className: 'text-xs bg-blue-500/20 text-blue-300 px-2 py-1 rounded-full font-medium'\n }, 'FREE'),\n React.createElement('span', {\n key: 'security-badge',\n className: `text-xs px-2 py-1 rounded-full font-medium ${type.securityColor}`\n }, type.securityBadge)\n ]),\n React.createElement('p', { \n key: 'duration', \n className: 'text-gray-300 font-medium mb-1' \n }, `Duration: ${type.duration}`),\n React.createElement('p', {\n key: 'description',\n className: 'text-sm text-gray-400'\n }, type.description)\n ]),\n React.createElement('div', { key: 'pricing', className: 'text-right' }, [\n React.createElement('div', { \n key: 'sats', \n className: `text-xl font-bold ${isDemo ? 'text-green-400' : 'text-orange-400'}` \n }, type.price),\n React.createElement('div', { \n key: 'usd', \n className: 'text-sm text-gray-400' \n }, type.usd)\n ])\n ]),\n\n // Demo status info\n isDemo && demoInfo && React.createElement('div', {\n key: 'demo-status',\n className: 'p-3 bg-blue-900/20 border border-blue-700/30 rounded-lg'\n }, [\n React.createElement('div', {\n key: 'availability',\n className: `text-sm font-medium ${demoInfo.canUseNow ? 'text-green-400' : 'text-yellow-400'}`\n }, demoInfo.canUseNow ? \n `\u2705 Available (${demoInfo.available}/${demoInfo.total} today)` : \n `\u23F0 Next: ${demoInfo.nextAvailable}`\n ),\n demoInfo.globalActive > 0 && React.createElement('div', {\n key: 'global-status',\n className: 'text-blue-300 text-xs mt-1'\n }, `\uD83C\uDF10 Global: ${demoInfo.globalActive}/${demoInfo.globalLimit} active`)\n ]),\n\n // Security features\n React.createElement('div', { key: 'features-section', className: 'space-y-3' }, [\n React.createElement('div', { key: 'features' }, [\n React.createElement('h5', {\n key: 'features-title',\n className: 'text-sm font-medium text-green-300 mb-2 flex items-center'\n }, [\n React.createElement('i', {\n key: 'shield-icon',\n className: 'fas fa-shield-alt mr-2'\n }),\n 'Security Features'\n ]),\n React.createElement('div', {\n key: 'features-list',\n className: 'grid grid-cols-1 gap-1'\n }, type.features.map((feature, index) => \n React.createElement('div', {\n key: index,\n className: 'flex items-center gap-2 text-xs text-gray-300'\n }, [\n React.createElement('i', {\n key: 'check',\n className: 'fas fa-check text-green-400 w-3'\n }),\n React.createElement('span', {\n key: 'text'\n }, feature)\n ])\n ))\n ]),\n\n // Limitations (if any)\n type.limitations && type.limitations.length > 0 && React.createElement('div', { key: 'limitations' }, [\n React.createElement('h5', {\n key: 'limitations-title',\n className: 'text-sm font-medium text-yellow-300 mb-2 flex items-center'\n }, [\n React.createElement('i', {\n key: 'info-icon',\n className: 'fas fa-info-circle mr-2'\n }),\n 'Limitations'\n ]),\n React.createElement('div', {\n key: 'limitations-list',\n className: 'grid grid-cols-1 gap-1'\n }, type.limitations.map((limitation, index) => \n React.createElement('div', {\n key: index,\n className: 'flex items-center gap-2 text-xs text-gray-400'\n }, [\n React.createElement('i', {\n key: 'minus',\n className: 'fas fa-minus text-yellow-400 w-3'\n }),\n React.createElement('span', {\n key: 'text'\n }, limitation)\n ])\n ))\n ])\n ])\n ])\n ])\n })\n ),\n \n demoInfo && React.createElement('div', { \n key: 'demo-info', \n className: 'bg-gradient-to-r from-blue-900/20 to-purple-900/20 border border-blue-700/50 rounded-lg p-4' \n }, [\n React.createElement('div', { \n key: 'demo-header', \n className: 'flex items-center gap-2 text-blue-300 text-sm font-medium mb-3' \n }, [\n React.createElement('i', {\n key: 'icon',\n className: 'fas fa-info-circle'\n }),\n React.createElement('span', {\n key: 'title'\n }, 'Demo Session Information')\n ]),\n React.createElement('div', { \n key: 'demo-details', \n className: 'grid grid-cols-1 md:grid-cols-2 gap-3 text-blue-200 text-xs' \n }, [\n React.createElement('div', { key: 'limits', className: 'space-y-1' }, [\n React.createElement('div', { key: 'daily' }, `\uD83D\uDCC5 Daily limit: ${demoInfo.total} sessions`),\n React.createElement('div', { key: 'duration' }, `\u23F1\uFE0F Duration: ${demoInfo.durationMinutes} minutes each`),\n React.createElement('div', { key: 'cooldown' }, `\u23F0 Cooldown: ${demoInfo.sessionCooldownMinutes} min between sessions`)\n ]),\n React.createElement('div', { key: 'status', className: 'space-y-1' }, [\n React.createElement('div', { key: 'used' }, `\uD83D\uDCCA Used today: ${demoInfo.used}/${demoInfo.total}`),\n React.createElement('div', { key: 'global' }, `\uD83C\uDF10 Global active: ${demoInfo.globalActive}/${demoInfo.globalLimit}`),\n React.createElement('div', { \n key: 'next', \n className: demoInfo.canUseNow ? 'text-green-300' : 'text-yellow-300' \n }, `\uD83C\uDFAF Status: ${demoInfo.canUseNow ? 'Available now' : demoInfo.nextAvailable}`)\n ])\n ]),\n React.createElement('div', {\n key: 'security-note',\n className: 'mt-3 p-2 bg-yellow-500/10 border border-yellow-500/20 rounded text-yellow-200 text-xs'\n }, '\u26A0\uFE0F Demo sessions use basic security only. Upgrade to paid sessions for enhanced protection.'),\n React.createElement('div', {\n key: 'last-updated',\n className: 'text-xs text-gray-400 mt-2 text-center'\n }, `Last updated: ${new Date(lastRefresh).toLocaleTimeString()}`)\n ]),\n\n // Action buttons\n React.createElement('div', { key: 'buttons', className: 'flex space-x-3' }, [\n React.createElement('button', { \n key: 'continue', \n onClick: () => {\n if (selectedType) {\n console.log(`\uD83D\uDE80 Proceeding with session type: ${selectedType}`);\n onSelectType(selectedType);\n }\n }, \n disabled: !selectedType || (selectedType === 'demo' && demoInfo && !demoInfo.canUseNow), \n className: 'flex-1 lightning-button text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50 disabled:cursor-not-allowed transition-all' \n }, [\n React.createElement('i', { \n key: 'icon',\n className: selectedType === 'demo' ? 'fas fa-play mr-2' : 'fas fa-bolt mr-2' \n }), \n selectedType === 'demo' ? 'Start Demo Session' : 'Continue to Payment'\n ]),\n React.createElement('button', { \n key: 'cancel', \n onClick: onCancel, \n className: 'px-6 py-3 bg-gray-600 hover:bg-gray-500 text-white rounded-lg transition-all' \n }, 'Cancel'),\n \n ])\n ]);\n};\n\nwindow.SessionTypeSelector = SessionTypeSelector;", "const React = window.React;\nconst { useState, useEffect } = React;\n\nconst IntegratedLightningPayment = ({ sessionType, onSuccess, onCancel, paymentManager }) => {\n const [paymentMethod, setPaymentMethod] = useState('webln');\n const [preimage, setPreimage] = useState('');\n const [isProcessing, setIsProcessing] = useState(false);\n const [error, setError] = useState('');\n const [invoice, setInvoice] = useState(null);\n const [paymentStatus, setPaymentStatus] = useState('pending'); // pending, created, paid, expired\n const [qrCodeUrl, setQrCodeUrl] = useState('');\n\n useEffect(() => {\n createInvoice();\n }, [sessionType]);\n\n const createInvoice = async () => {\n if (sessionType === 'free') {\n setPaymentStatus('free');\n return;\n }\n\n setIsProcessing(true);\n setError('');\n\n try {\n \n if (!paymentManager) {\n throw new Error('Payment manager not available. Please check sessionManager initialization.');\n }\n\n const createdInvoice = await paymentManager.createLightningInvoice(sessionType);\n\n if (!createdInvoice) {\n throw new Error('Failed to create invoice');\n }\n\n setInvoice(createdInvoice);\n setPaymentStatus('created');\n\n if (createdInvoice.paymentRequest) {\n try {\n const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300, margin: 2, errorCorrectionLevel: 'M' });\n setQrCodeUrl(dataUrl);\n } catch (e) {\n console.warn('QR local generation failed, showing placeholder');\n const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300 });\n setQrCodeUrl(dataUrl);\n }\n }\n\n } catch (err) {\n console.error('Invoice creation failed:', err);\n setError(`Error creating invoice: ${err.message}`);\n } finally {\n setIsProcessing(false);\n }\n };\n\n const handleWebLNPayment = async () => {\n if (!window.webln) {\n setError('WebLN is not supported. Please use the Alby or Zeus wallet. SecureBit.chat v4.02.442 - ASN.1 Validated requires WebLN for Lightning payments.');\n return;\n }\n\n if (!invoice || !invoice.paymentRequest) {\n setError('Invoice is not ready for payment');\n return;\n }\n\n setIsProcessing(true);\n setError('');\n\n try {\n await window.webln.enable();\n \n const result = await window.webln.sendPayment(invoice.paymentRequest);\n \n if (result.preimage) {\n setPaymentStatus('paid');\n await activateSession(result.preimage);\n } else {\n setError('Payment does not contain preimage');\n }\n } catch (err) {\n console.error('WebLN payment failed:', err);\n setError(`WebLN Error: ${err.message}`);\n } finally {\n setIsProcessing(false);\n }\n };\n\n const handleManualVerification = async () => {\n const trimmedPreimage = preimage.trim();\n \n if (!trimmedPreimage) {\n setError('Enter payment preimage');\n return;\n }\n \n if (trimmedPreimage.length !== 64) {\n setError('The preimage must be exactly 64 characters long.');\n return;\n }\n \n if (!/^[0-9a-fA-F]{64}$/.test(trimmedPreimage)) {\n setError('The preimage must contain only hexadecimal characters (0-9, a-f, A-F).');\n return;\n }\n \n if (trimmedPreimage === '1'.repeat(64) || \n trimmedPreimage === 'a'.repeat(64) || \n trimmedPreimage === 'f'.repeat(64)) {\n setError('The entered preimage is too weak. Please verify the key..');\n return;\n }\n \n setError('');\n setIsProcessing(true);\n\n try {\n await activateSession(trimmedPreimage);\n } catch (err) {\n setError(`Activation error: ${err.message}`);\n } finally {\n setIsProcessing(false);\n }\n };\n\n const activateSession = async (preimageValue) => {\n try {\n \n let result;\n if (paymentManager) {\n const paymentHash = invoice?.paymentHash || 'dummy_hash';\n result = await paymentManager.safeActivateSession(sessionType, preimageValue, paymentHash);\n } else {\n console.warn('Payment manager not available, using fallback');\n // Fallback if paymentManager is unavailable\n result = { success: true, method: 'fallback' };\n }\n\n if (result.success) {\n setPaymentStatus('paid');\n onSuccess(preimageValue, invoice);\n } else {\n console.error('\u274C Session activation failed:', result);\n throw new Error(`Session activation failed: ${result.reason}`);\n }\n\n } catch (err) {\n console.error('\u274C Session activation failed:', err);\n throw err;\n }\n };\n\n const handleFreeSession = async () => {\n setIsProcessing(true);\n try {\n await activateSession('0'.repeat(64));\n } catch (err) {\n setError(`Free session activation error: ${err.message}`);\n } finally {\n setIsProcessing(false);\n }\n };\n\n const copyToClipboard = (text) => {\n navigator.clipboard.writeText(text).then(() => {\n });\n };\n\n const pricing = {\n free: { sats: 1, hours: 1/60 },\n basic: { sats: 500, hours: 1 },\n premium: { sats: 1000, hours: 4 },\n extended: { sats: 2000, hours: 24 }\n }[sessionType];\n\n return React.createElement('div', { className: 'space-y-4 max-w-md mx-auto' }, [\n React.createElement('div', { key: 'header', className: 'text-center' }, [\n React.createElement('h3', { \n key: 'title', \n className: 'text-xl font-semibold text-white mb-2' \n }, sessionType === 'free' ? 'Free session' : 'Lightning payment'),\n React.createElement('div', { \n key: 'amount', \n className: 'text-2xl font-bold text-orange-400' \n }, sessionType === 'free' \n ? '0 sat per minute' \n : `${pricing.sats} \u0441\u0430\u0442 \u0437\u0430 ${pricing.hours}\u0447`\n ),\n sessionType !== 'free' && React.createElement('div', { \n key: 'usd', \n className: 'text-sm text-gray-400 mt-1' \n }, `\u2248 $${(pricing.sats * 0.0004).toFixed(2)} USD`)\n ]),\n\n // Loading State\n isProcessing && paymentStatus === 'pending' && React.createElement('div', { \n key: 'loading', \n className: 'text-center' \n }, [\n React.createElement('div', { \n key: 'spinner', \n className: 'text-orange-400' \n }, [\n React.createElement('i', { className: 'fas fa-spinner fa-spin mr-2' }),\n 'Creating invoice...'\n ])\n ]),\n\n // Free Session\n sessionType === 'free' && React.createElement('div', { \n key: 'free-session', \n className: 'space-y-3' \n }, [\n React.createElement('div', { \n key: 'info', \n className: 'p-3 bg-blue-500/10 border border-blue-500/20 rounded text-blue-300 text-sm' \n }, 'A free 1-minute session will be activated.'),\n React.createElement('button', { \n key: 'start-btn',\n onClick: handleFreeSession,\n disabled: isProcessing,\n className: 'w-full bg-blue-600 hover:bg-blue-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50'\n }, [\n React.createElement('i', { \n key: 'icon',\n className: `fas ${isProcessing ? 'fa-spinner fa-spin' : 'fa-play'} mr-2` \n }),\n isProcessing ? 'Activation...' : 'Start free session'\n ])\n ]),\n\n // Paid Sessions\n sessionType !== 'free' && paymentStatus === 'created' && invoice && React.createElement('div', { \n key: 'paid-session', \n className: 'space-y-4' \n }, [\n // QR Code\n qrCodeUrl && React.createElement('div', { \n key: 'qr-section', \n className: 'text-center' \n }, [\n React.createElement('div', { \n key: 'qr-container', \n className: 'bg-white p-4 rounded-lg inline-block' \n }, [\n React.createElement('img', { \n key: 'qr-img',\n src: qrCodeUrl, \n alt: 'Payment QR Code', \n className: 'w-48 h-48' \n })\n ]),\n React.createElement('div', { \n key: 'qr-hint', \n className: 'text-xs text-gray-400 mt-2' \n }, 'Scan the QR code with any Lightning wallet')\n ]),\n\n // Payment Request\n invoice.paymentRequest && React.createElement('div', { \n key: 'payment-request', \n className: 'space-y-2' \n }, [\n React.createElement('div', { \n key: 'label', \n className: 'text-sm font-medium text-white' \n }, 'Payment Request:'),\n React.createElement('div', { \n key: 'request',\n className: 'p-3 bg-gray-800 rounded border text-xs font-mono text-gray-300 cursor-pointer hover:bg-gray-700',\n onClick: () => copyToClipboard(invoice.paymentRequest)\n }, [\n invoice.paymentRequest.substring(0, 50) + '...',\n React.createElement('i', { key: 'copy-icon', className: 'fas fa-copy ml-2 text-orange-400' })\n ])\n ]),\n\n // WebLN Payment\n React.createElement('div', { \n key: 'webln-section', \n className: 'space-y-3' \n }, [\n React.createElement('h4', { \n key: 'webln-title', \n className: 'text-white font-medium flex items-center' \n }, [\n React.createElement('i', { key: 'bolt-icon', className: 'fas fa-bolt text-orange-400 mr-2' }),\n 'WebLN wallet (Alby, Zeus)'\n ]),\n React.createElement('button', { \n key: 'webln-btn',\n onClick: handleWebLNPayment,\n disabled: isProcessing,\n className: 'w-full bg-orange-600 hover:bg-orange-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50'\n }, [\n React.createElement('i', { \n key: 'webln-icon',\n className: `fas ${isProcessing ? 'fa-spinner fa-spin' : 'fa-bolt'} mr-2` \n }),\n isProcessing ? 'Processing...' : 'Pay via WebLN'\n ])\n ]),\n\n // Manual Payment\n React.createElement('div', { \n key: 'divider', \n className: 'text-center text-gray-400' \n }, 'or'),\n \n React.createElement('div', { \n key: 'manual-section', \n className: 'space-y-3' \n }, [\n React.createElement('h4', { \n key: 'manual-title', \n className: 'text-white font-medium' \n }, 'Manual payment verification'),\n React.createElement('input', { \n key: 'preimage-input',\n type: 'text',\n value: preimage,\n onChange: (e) => setPreimage(e.target.value),\n placeholder: 'Enter the preimage after payment...',\n className: 'w-full p-3 bg-gray-800 border border-gray-600 rounded text-white placeholder-gray-400 text-sm'\n }),\n React.createElement('button', { \n key: 'verify-btn',\n onClick: handleManualVerification,\n disabled: isProcessing,\n className: 'w-full bg-green-600 hover:bg-green-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50'\n }, [\n React.createElement('i', { \n key: 'verify-icon',\n className: `fas ${isProcessing ? 'fa-spinner fa-spin' : 'fa-check'} mr-2` \n }),\n isProcessing ? 'Verification...' : 'Confirm payment'\n ])\n ])\n ]),\n\n // Success State\n paymentStatus === 'paid' && React.createElement('div', { \n key: 'success', \n className: 'text-center p-4 bg-green-500/10 border border-green-500/20 rounded' \n }, [\n React.createElement('i', { key: 'success-icon', className: 'fas fa-check-circle text-green-400 text-2xl mb-2' }),\n React.createElement('div', { key: 'success-text', className: 'text-green-300 font-medium' }, 'Payment confirmed!'),\n React.createElement('div', { key: 'success-subtext', className: 'text-green-400 text-sm' }, 'Session activated')\n ]),\n\n // Error State\n error && React.createElement('div', { \n key: 'error', \n className: 'p-3 bg-red-500/10 border border-red-500/20 rounded text-red-400 text-sm' \n }, [\n React.createElement('i', { key: 'error-icon', className: 'fas fa-exclamation-triangle mr-2' }),\n error,\n error.includes('invoice') && React.createElement('button', { \n key: 'retry-btn',\n onClick: createInvoice,\n className: 'ml-2 text-orange-400 hover:text-orange-300 underline'\n }, 'Try again')\n ]),\n\n // Cancel Button\n React.createElement('button', { \n key: 'cancel-btn',\n onClick: onCancel,\n className: 'w-full bg-gray-600 hover:bg-gray-500 text-white py-2 px-4 rounded'\n }, 'Cancel')\n ]);\n};\n\nwindow.LightningPayment = IntegratedLightningPayment;", "const React = window.React;\nconst { useState, useEffect, useRef } = React;\n\nconst PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) => {\n const [step, setStep] = React.useState('select');\n const [selectedType, setSelectedType] = React.useState(null);\n const [invoice, setInvoice] = React.useState(null);\n const [paymentStatus, setPaymentStatus] = React.useState('pending');\n const [error, setError] = React.useState('');\n const [paymentMethod, setPaymentMethod] = React.useState('webln'); \n const [preimageInput, setPreimageInput] = React.useState('');\n const [isProcessing, setIsProcessing] = React.useState(false);\n const [qrCodeUrl, setQrCodeUrl] = React.useState('');\n const [paymentTimer, setPaymentTimer] = React.useState(null);\n const [timeLeft, setTimeLeft] = React.useState(0);\n const [showSecurityDetails, setShowSecurityDetails] = React.useState(false);\n const pollInterval = React.useRef(null);\n\n React.useEffect(() => {\n if (!isOpen) {\n resetModal();\n if (pollInterval.current) {\n clearInterval(pollInterval.current);\n }\n if (paymentTimer) {\n clearInterval(paymentTimer);\n }\n }\n }, [isOpen]);\n\n const resetModal = () => {\n setStep('select');\n setSelectedType(null);\n setInvoice(null);\n setPaymentStatus('pending');\n setError('');\n setPaymentMethod('webln');\n setPreimageInput('');\n setIsProcessing(false);\n setQrCodeUrl('');\n setTimeLeft(0);\n setShowSecurityDetails(false);\n };\n\n const getSecurityFeaturesInfo = (sessionType) => {\n const features = {\n demo: {\n title: 'Demo Session - Basic Security',\n description: 'Limited testing session with basic security features',\n available: [\n '\uD83D\uDD10 Basic end-to-end encryption (AES-GCM 256)',\n '\uD83D\uDD11 Simple key exchange (ECDH P-384)',\n '\u2705 Message integrity verification',\n '\u26A1 Rate limiting protection'\n ],\n unavailable: [\n '\uD83D\uDD10 ECDSA Digital Signatures',\n '\uD83D\uDEE1\uFE0F Metadata Protection',\n '\uD83D\uDD04 Perfect Forward Secrecy',\n '\uD83D\uDD10 Nested Encryption',\n '\uD83D\uDCE6 Packet Padding',\n '\uD83C\uDFAD Traffic Obfuscation',\n '\uD83C\uDFAA Fake Traffic Generation',\n '\uD83D\uDD75\uFE0F Decoy Channels',\n '\uD83D\uDEAB Anti-Fingerprinting',\n '\uD83D\uDCDD Message Chunking',\n '\uD83D\uDD04 Advanced Replay Protection'\n ],\n upgrade: {\n next: 'Basic Session (5,000 sat - $2.00)',\n features: [\n '\uD83D\uDD10 ECDSA Digital Signatures',\n '\uD83D\uDEE1\uFE0F Metadata Protection',\n '\uD83D\uDD04 Perfect Forward Secrecy',\n '\uD83D\uDD10 Nested Encryption',\n '\uD83D\uDCE6 Packet Padding'\n ]\n }\n },\n basic: {\n title: 'Basic Session - Enhanced Security',\n description: 'Full featured session with enhanced security features',\n available: [\n '\uD83D\uDD10 Basic end-to-end encryption (AES-GCM 256)',\n '\uD83D\uDD11 Simple key exchange (ECDH P-384)',\n '\u2705 Message integrity verification',\n '\u26A1 Rate limiting protection',\n '\uD83D\uDD10 ECDSA Digital Signatures',\n '\uD83D\uDEE1\uFE0F Metadata Protection',\n '\uD83D\uDD04 Perfect Forward Secrecy',\n '\uD83D\uDD10 Nested Encryption',\n '\uD83D\uDCE6 Packet Padding',\n '\uD83D\uDD12 Complete ASN.1 validation',\n '\uD83D\uDD0D OID and EC point verification',\n '\uD83C\uDFD7\uFE0F SPKI structure validation',\n '\uD83D\uDEE1\uFE0F 18-layer security architecture'\n ],\n unavailable: [\n '\uD83C\uDFAD Traffic Obfuscation',\n '\uD83C\uDFAA Fake Traffic Generation',\n '\uD83D\uDD75\uFE0F Decoy Channels',\n '\uD83D\uDEAB Anti-Fingerprinting',\n '\uD83D\uDCDD Message Chunking',\n '\uD83D\uDD04 Advanced Replay Protection'\n ],\n upgrade: {\n next: 'Premium Session (20,000 sat - $8.00)',\n features: [\n '\uD83C\uDFAD Traffic Obfuscation',\n '\uD83C\uDFAA Fake Traffic Generation',\n '\uD83D\uDD75\uFE0F Decoy Channels',\n '\uD83D\uDEAB Anti-Fingerprinting',\n '\uD83D\uDCDD Message Chunking',\n '\uD83D\uDD04 Advanced Replay Protection'\n ]\n }\n },\n premium: {\n title: 'Premium Session - Maximum Security',\n description: 'Extended session with maximum security protection',\n available: [\n '\uD83D\uDD10 Basic end-to-end encryption (AES-GCM 256)',\n '\uD83D\uDD11 Simple key exchange (ECDH P-384)',\n '\u2705 Message integrity verification',\n '\u26A1 Rate limiting protection',\n '\uD83D\uDD10 ECDSA Digital Signatures',\n '\uD83D\uDEE1\uFE0F Metadata Protection',\n '\uD83D\uDD04 Perfect Forward Secrecy',\n '\uD83D\uDD10 Nested Encryption',\n '\uD83D\uDCE6 Packet Padding',\n '\uD83C\uDFAD Traffic Obfuscation',\n '\uD83C\uDFAA Fake Traffic Generation',\n '\uD83D\uDD75\uFE0F Decoy Channels',\n '\uD83D\uDEAB Anti-Fingerprinting',\n '\uD83D\uDCDD Message Chunking',\n '\uD83D\uDD04 Advanced Replay Protection',\n '\uD83D\uDD12 Complete ASN.1 validation',\n '\uD83D\uDD0D OID and EC point verification',\n '\uD83C\uDFD7\uFE0F SPKI structure validation',\n '\uD83D\uDEE1\uFE0F 18-layer security architecture',\n '\uD83D\uDE80 ASN.1 Validated'\n ],\n unavailable: [],\n upgrade: {\n next: 'Maximum security achieved!',\n features: ['\uD83C\uDF89 All security features unlocked!']\n }\n }\n };\n \n return features[sessionType] || features.demo;\n };\n\n const handleSelectType = async (type) => {\n setSelectedType(type);\n setError('');\n \n if (type === 'demo') {\n try {\n if (!sessionManager || !sessionManager.createDemoSession) {\n throw new Error('Demo session manager not available');\n }\n \n const demoSession = sessionManager.createDemoSession();\n if (!demoSession.success) {\n throw new Error(demoSession.reason);\n }\n \n setInvoice({ \n sessionType: 'demo',\n amount: 0,\n paymentHash: demoSession.paymentHash,\n memo: `Demo session (${demoSession.durationMinutes} minutes)`,\n createdAt: Date.now(),\n isDemo: true,\n preimage: demoSession.preimage,\n warning: demoSession.warning,\n securityLevel: 'Basic'\n });\n setPaymentStatus('demo');\n } catch (error) {\n setError(`Demo session creation failed: ${error.message}`);\n return;\n }\n } else {\n await createRealInvoice(type);\n }\n setStep('payment');\n };\n\n const createRealInvoice = async (type) => {\n setPaymentStatus('creating');\n setIsProcessing(true);\n setError('');\n\n try {\n console.log(`Creating Lightning invoice for ${type} session...`);\n \n if (!sessionManager) {\n throw new Error('Session manager not initialized');\n }\n\n const createdInvoice = await sessionManager.createLightningInvoice(type);\n \n if (!createdInvoice || !createdInvoice.paymentRequest) {\n throw new Error('Failed to create Lightning invoice');\n }\n\n createdInvoice.securityLevel = sessionManager.getSecurityLevelForSession(type);\n\n setInvoice(createdInvoice);\n setPaymentStatus('created');\n\n try {\n const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300, margin: 2, errorCorrectionLevel: 'M' });\n setQrCodeUrl(dataUrl);\n } catch (e) {\n console.warn('QR local generation failed, showing placeholder');\n const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300 });\n setQrCodeUrl(dataUrl);\n }\n\n const expirationTime = 15 * 60 * 1000;\n setTimeLeft(expirationTime);\n \n const timer = setInterval(() => {\n setTimeLeft(prev => {\n const newTime = prev - 1000;\n if (newTime <= 0) {\n clearInterval(timer);\n setPaymentStatus('expired');\n setError('Payment time has expired. Create a new invoice.');\n return 0;\n }\n return newTime;\n });\n }, 1000);\n setPaymentTimer(timer);\n\n startPaymentPolling(createdInvoice.checkingId);\n\n console.log('\u2705 Lightning invoice created successfully:', createdInvoice);\n\n } catch (err) {\n console.error('\u274C Invoice creation failed:', err);\n setError(`Invoice creation error: ${err.message}`);\n setPaymentStatus('failed');\n } finally {\n setIsProcessing(false);\n }\n };\n\n const startPaymentPolling = (checkingId) => {\n if (pollInterval.current) {\n clearInterval(pollInterval.current);\n }\n\n pollInterval.current = setInterval(async () => {\n try {\n const status = await sessionManager.checkPaymentStatus(checkingId);\n \n if (status.paid && status.preimage) {\n clearInterval(pollInterval.current);\n setPaymentStatus('paid');\n await handlePaymentSuccess(status.preimage);\n }\n } catch (error) {\n console.warn('Payment status check failed:', error);\n }\n }, 3000); \n };\n\n const handleWebLNPayment = async () => {\n if (!window.webln) {\n setError('WebLN is not supported. Please install the Alby or Zeus wallet.');\n return;\n }\n\n if (!invoice || !invoice.paymentRequest) {\n setError('Invoice is not ready for payment.');\n return;\n }\n\n setIsProcessing(true);\n setError('');\n setPaymentStatus('paying');\n\n try {\n await window.webln.enable();\n \n const result = await window.webln.sendPayment(invoice.paymentRequest);\n \n if (result.preimage) {\n setPaymentStatus('paid');\n await handlePaymentSuccess(result.preimage);\n } else {\n throw new Error('Payment does not contain preimage');\n }\n } catch (err) {\n console.error('\u274C WebLN payment failed:', err);\n setError(`WebLN payment error: ${err.message}`);\n setPaymentStatus('created'); \n } finally {\n setIsProcessing(false);\n }\n };\n\n const handleManualVerification = async () => {\n const trimmedPreimage = preimageInput.trim();\n \n if (!trimmedPreimage) {\n setError('Enter payment preimage');\n return;\n }\n \n if (trimmedPreimage.length !== 64) {\n setError('The preimage must be exactly 64 characters long.');\n return;\n }\n \n if (!/^[0-9a-fA-F]{64}$/.test(trimmedPreimage)) {\n setError('The preimage must contain only hexadecimal characters (0-9, a-f, A-F).');\n return;\n }\n \n const dummyPreimages = ['1'.repeat(64), 'a'.repeat(64), 'f'.repeat(64), '0'.repeat(64)];\n if (dummyPreimages.includes(trimmedPreimage) && selectedType !== 'demo') {\n setError('The entered preimage is invalid. Please use the actual preimage from the payment.');\n return;\n }\n \n setIsProcessing(true);\n setError('');\n setPaymentStatus('paying');\n\n try {\n await handlePaymentSuccess(trimmedPreimage);\n } catch (err) {\n setError(err.message);\n setPaymentStatus('created');\n } finally {\n setIsProcessing(false);\n }\n };\n\n const handleDemoSession = async () => {\n setIsProcessing(true);\n setError('');\n \n try {\n if (!invoice?.preimage) {\n throw new Error('Demo preimage not available');\n }\n \n const isValid = await sessionManager.verifyPayment(invoice.preimage, invoice.paymentHash);\n \n if (isValid && isValid.verified) {\n onSessionPurchased({ \n type: 'demo', \n preimage: invoice.preimage,\n paymentHash: invoice.paymentHash,\n amount: 0,\n isDemo: true,\n warning: invoice.warning,\n securityLevel: 'basic'\n });\n \n setTimeout(() => {\n onClose();\n }, 1500);\n } else {\n throw new Error(isValid?.reason || 'Demo session verification failed');\n }\n } catch (err) {\n setError(`Demo session activation error: ${err.message}`);\n } finally {\n setIsProcessing(false);\n }\n };\n\n const handlePaymentSuccess = async (preimage) => {\n try {\n console.log('\uD83D\uDD0D Verifying payment...', { selectedType, preimage });\n \n let isValid;\n if (selectedType === 'demo') {\n return;\n } else {\n isValid = await sessionManager.verifyPayment(preimage, invoice.paymentHash);\n }\n \n if (isValid) {\n if (pollInterval.current) {\n clearInterval(pollInterval.current);\n }\n if (paymentTimer) {\n clearInterval(paymentTimer);\n }\n\n onSessionPurchased({ \n type: selectedType, \n preimage,\n paymentHash: invoice.paymentHash,\n amount: invoice.amount,\n securityLevel: invoice.securityLevel || (selectedType === 'basic' ? 'enhanced' : 'maximum')\n });\n \n setTimeout(() => {\n onClose();\n }, 1500);\n \n } else {\n throw new Error('Payment verification failed. Please check the preimage for correctness or try again.');\n }\n } catch (error) {\n console.error('\u274C Payment verification failed:', error);\n throw error;\n }\n };\n\n const copyToClipboard = async (text) => {\n try {\n await navigator.clipboard.writeText(text);\n } catch (err) {\n console.error('Failed to copy:', err);\n }\n };\n\n const formatTime = (ms) => {\n const minutes = Math.floor(ms / 60000);\n const seconds = Math.floor((ms % 60000) / 1000);\n return `${minutes}:${seconds.toString().padStart(2, '0')}`;\n };\n\n const getSecurityBadgeColor = (level) => {\n switch (level?.toLowerCase()) {\n case 'basic': return 'bg-blue-500/20 text-blue-300 border-blue-500/30';\n case 'enhanced': return 'bg-orange-500/20 text-orange-300 border-orange-500/30';\n case 'maximum': return 'bg-green-500/20 text-green-300 border-green-500/30';\n default: return 'bg-gray-500/20 text-gray-300 border-gray-500/30';\n }\n };\n\n const pricing = sessionManager?.sessionPrices || {\n demo: { sats: 0, hours: 0.1, usd: 0.00 },\n basic: { sats: 5000, hours: 1, usd: 2.00 },\n premium: { sats: 20000, hours: 6, usd: 8.00 }\n };\n\n if (!isOpen) return null;\n\n return React.createElement('div', { \n className: 'fixed inset-0 bg-black/80 backdrop-blur-sm z-50 flex items-center justify-center p-4' \n }, [\n React.createElement('div', { \n key: 'modal', \n className: 'card-minimal rounded-xl p-6 max-w-lg w-full max-h-[90vh] overflow-y-auto custom-scrollbar' \n }, [\n React.createElement('div', { \n key: 'header', \n className: 'flex items-center justify-between mb-6' \n }, [\n React.createElement('h2', { \n key: 'title', \n className: 'text-xl font-semibold text-primary' \n }, step === 'select' ? 'Select session type' : \n step === 'details' ? 'Security Features Details' : 'Session payment'),\n React.createElement('button', { \n key: 'close',\n onClick: onClose, \n className: 'text-gray-400 hover:text-white transition-colors' \n }, React.createElement('i', { className: 'fas fa-times' }))\n ]),\n\n step === 'select' && window.SessionTypeSelector && React.createElement(window.SessionTypeSelector, { \n key: 'selector', \n onSelectType: handleSelectType, \n onCancel: onClose,\n sessionManager: sessionManager\n }),\n\n step === 'payment' && React.createElement('div', { \n key: 'payment-step', \n className: 'space-y-6' \n }, [\n React.createElement('div', { \n key: 'session-info', \n className: 'text-center p-4 bg-orange-500/10 border border-orange-500/20 rounded-lg' \n }, [\n React.createElement('h3', { \n key: 'session-title', \n className: 'text-lg font-semibold text-orange-400 mb-2' \n }, [\n `${selectedType.charAt(0).toUpperCase() + selectedType.slice(1)} session`,\n invoice?.securityLevel && React.createElement('span', {\n key: 'security-badge',\n className: `text-xs px-2 py-1 rounded-full border ${getSecurityBadgeColor(invoice.securityLevel)}`\n }, invoice.securityLevel.toUpperCase())\n ]),\n React.createElement('div', { \n key: 'session-details', \n className: 'text-sm text-secondary' \n }, [\n React.createElement('div', { key: 'amount' }, `${pricing[selectedType].sats} sat for ${pricing[selectedType].hours}h`),\n pricing[selectedType].usd > 0 && React.createElement('div', { \n key: 'usd', \n className: 'text-gray-400' \n }, `\u2248 ${pricing[selectedType].usd} USD`),\n React.createElement('button', {\n key: 'details-btn',\n onClick: () => setStep('details'),\n className: 'mt-2 text-xs text-blue-400 hover:text-blue-300 underline cursor-pointer'\n }, '\uD83D\uDCCB View Security Details')\n ])\n ]),\n\n timeLeft > 0 && paymentStatus === 'created' && React.createElement('div', { \n key: 'timer', \n className: 'text-center p-3 bg-yellow-500/10 border border-yellow-500/20 rounded' \n }, [\n React.createElement('div', { \n key: 'timer-text', \n className: 'text-yellow-400 font-medium' \n }, `\u23F1\uFE0F Time to pay: ${formatTime(timeLeft)}`)\n ]),\n\n paymentStatus === 'demo' && React.createElement('div', { \n key: 'demo-payment', \n className: 'space-y-4' \n }, [\n React.createElement('div', { \n key: 'demo-info', \n className: 'p-4 bg-green-500/10 border border-green-500/20 rounded text-green-300 text-sm text-center' \n }, [\n React.createElement('div', { key: 'demo-title', className: 'font-medium mb-1' }, '\uD83C\uDFAE Demo Session Available'),\n React.createElement('div', { key: 'demo-details', className: 'text-xs' }, \n `Limited to ${invoice?.durationMinutes || 6} minutes for testing`)\n ]),\n invoice?.warning && React.createElement('div', {\n key: 'demo-warning',\n className: 'p-3 bg-yellow-500/10 border border-yellow-500/20 rounded text-yellow-300 text-xs text-center'\n }, invoice.warning),\n React.createElement('div', {\n key: 'demo-preimage',\n className: 'p-3 bg-gray-800/50 rounded border border-gray-600 text-xs font-mono text-gray-300'\n }, [\n React.createElement('div', { key: 'preimage-label', className: 'text-gray-400 mb-1' }, 'Demo Preimage:'),\n React.createElement('div', { key: 'preimage-value', className: 'break-all' }, \n invoice?.preimage || 'Generating...')\n ]),\n React.createElement('button', { \n key: 'demo-btn',\n onClick: handleDemoSession,\n disabled: isProcessing,\n className: 'w-full bg-green-600 hover:bg-green-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50 disabled:cursor-not-allowed'\n }, [\n React.createElement('i', { \n key: 'demo-icon',\n className: `fas ${isProcessing ? 'fa-spinner fa-spin' : 'fa-play'} mr-2` \n }),\n isProcessing ? 'Activating...' : 'Activate Demo Session'\n ])\n ]),\n\n paymentStatus === 'creating' && React.createElement('div', { \n key: 'creating', \n className: 'text-center p-4' \n }, [\n React.createElement('i', { className: 'fas fa-spinner fa-spin text-orange-400 text-2xl mb-2' }),\n React.createElement('div', { className: 'text-primary' }, 'Creating Lightning invoice...'),\n React.createElement('div', { className: 'text-secondary text-sm mt-1' }, 'Connecting to the Lightning Network...')\n ]),\n\n (paymentStatus === 'created' || paymentStatus === 'paying') && invoice && React.createElement('div', { \n key: 'payment-methods', \n className: 'space-y-6' \n }, [\n qrCodeUrl && React.createElement('div', { \n key: 'qr-section', \n className: 'text-center' \n }, [\n React.createElement('div', { \n key: 'qr-container', \n className: 'bg-white p-4 rounded-lg inline-block' \n }, [\n React.createElement('img', { \n key: 'qr-img',\n src: qrCodeUrl, \n alt: 'Lightning Payment QR Code', \n className: 'w-48 h-48' \n })\n ]),\n React.createElement('div', { \n key: 'qr-hint', \n className: 'text-xs text-gray-400 mt-2' \n }, 'Scan with any Lightning wallet')\n ]),\n\n invoice.paymentRequest && React.createElement('div', { \n key: 'payment-request', \n className: 'space-y-2' \n }, [\n React.createElement('div', { \n key: 'pr-label', \n className: 'text-sm font-medium text-primary' \n }, 'Lightning Payment Request:'),\n React.createElement('div', { \n key: 'pr-container',\n className: 'p-3 bg-gray-800/50 rounded border border-gray-600 text-xs font-mono text-gray-300 cursor-pointer hover:bg-gray-700/50 transition-colors',\n onClick: () => copyToClipboard(invoice.paymentRequest),\n title: 'Click to copy'\n }, [\n invoice.paymentRequest.substring(0, 60) + '...',\n React.createElement('i', { key: 'copy-icon', className: 'fas fa-copy ml-2 text-orange-400' })\n ])\n ]),\n\n // WebLN Payment\n React.createElement('div', { \n key: 'webln-section', \n className: 'space-y-3' \n }, [\n React.createElement('h4', { \n key: 'webln-title', \n className: 'text-primary font-medium flex items-center' \n }, [\n React.createElement('i', { key: 'bolt-icon', className: 'fas fa-bolt text-orange-400 mr-2' }),\n 'WebLN wallet (recommended)'\n ]),\n React.createElement('div', { \n key: 'webln-info', \n className: 'text-xs text-gray-400 mb-2' \n }, 'Alby, Zeus, or other WebLN-compatible wallets'),\n React.createElement('button', { \n key: 'webln-btn',\n onClick: handleWebLNPayment,\n disabled: isProcessing || paymentStatus === 'paying',\n className: 'w-full bg-orange-600 hover:bg-orange-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50 disabled:cursor-not-allowed transition-colors'\n }, [\n React.createElement('i', { \n key: 'webln-icon',\n className: `fas ${isProcessing ? 'fa-spinner fa-spin' : 'fa-bolt'} mr-2` \n }),\n paymentStatus === 'paying' ? 'Processing payment...' : 'Pay via WebLN'\n ])\n ]),\n\n // Divider\n React.createElement('div', { \n key: 'divider', \n className: 'text-center text-gray-400 text-sm' \n }, '\u2014 or \u2014'),\n \n // Manual Verification\n React.createElement('div', { \n key: 'manual-section', \n className: 'space-y-3' \n }, [\n React.createElement('h4', { \n key: 'manual-title', \n className: 'text-primary font-medium' \n }, 'Manual payment confirmation'),\n React.createElement('div', { \n key: 'manual-info', \n className: 'text-xs text-gray-400' \n }, 'Pay the invoice in any wallet and enter the preimage.:'),\n React.createElement('input', { \n key: 'preimage-input',\n type: 'text',\n value: preimageInput,\n onChange: (e) => setPreimageInput(e.target.value),\n placeholder: 'Enter the preimage (64 hex characters)...',\n className: 'w-full p-3 bg-gray-800 border border-gray-600 rounded text-white placeholder-gray-400 text-sm font-mono',\n maxLength: 64\n }),\n React.createElement('button', { \n key: 'verify-btn',\n onClick: handleManualVerification,\n disabled: isProcessing || !preimageInput.trim(),\n className: 'w-full bg-green-600 hover:bg-green-500 text-white py-3 px-4 rounded-lg font-medium disabled:opacity-50 disabled:cursor-not-allowed transition-colors'\n }, [\n React.createElement('i', { \n key: 'verify-icon',\n className: `fas ${isProcessing ? 'fa-spinner fa-spin' : 'fa-check'} mr-2` \n }),\n isProcessing ? 'Checking payment...' : 'Confirm payment'\n ])\n ])\n ]),\n\n // Success State\n paymentStatus === 'paid' && React.createElement('div', { \n key: 'success', \n className: 'text-center p-6 bg-green-500/10 border border-green-500/20 rounded-lg' \n }, [\n React.createElement('i', { key: 'success-icon', className: 'fas fa-check-circle text-green-400 text-3xl mb-3' }),\n React.createElement('div', { key: 'success-title', className: 'text-green-300 font-semibold text-lg mb-1' }, '\u2705 Payment confirmed!'),\n React.createElement('div', { key: 'success-text', className: 'text-green-400 text-sm' }, 'The session will be activated upon connecting to the chat.')\n ]),\n\n // Error State\n error && React.createElement('div', { \n key: 'error', \n className: 'p-4 bg-red-500/10 border border-red-500/20 rounded-lg' \n }, [\n React.createElement('div', { \n key: 'error-content', \n className: 'flex items-start space-x-3' \n }, [\n React.createElement('i', { key: 'error-icon', className: 'fas fa-exclamation-triangle text-red-400 mt-0.5' }),\n React.createElement('div', { key: 'error-text', className: 'flex-1' }, [\n React.createElement('div', { key: 'error-message', className: 'text-red-400 text-sm' }, error),\n (error.includes('invoice') || paymentStatus === 'failed') && React.createElement('button', { \n key: 'retry-btn',\n onClick: () => createRealInvoice(selectedType),\n className: 'mt-2 text-orange-400 hover:text-orange-300 underline text-sm'\n }, 'Create a new invoice')\n ])\n ])\n ]),\n\n paymentStatus !== 'paid' && React.createElement('div', { \n key: 'back-section', \n className: 'pt-4 border-t border-gray-600' \n }, [\n React.createElement('button', { \n key: 'back-btn',\n onClick: () => setStep('select'),\n className: 'w-full bg-gray-600 hover:bg-gray-500 text-white py-2 px-4 rounded transition-colors'\n }, [\n React.createElement('i', { key: 'back-icon', className: 'fas fa-arrow-left mr-2' }),\n 'Choose another session'\n ])\n ])\n ]),\n\n // Security Details Step\n step === 'details' && React.createElement('div', { \n key: 'details-step', \n className: 'space-y-6' \n }, [\n React.createElement('div', { \n key: 'details-header', \n className: 'text-center p-4 bg-blue-500/10 border border-blue-500/20 rounded-lg' \n }, [\n React.createElement('h3', { \n key: 'details-title', \n className: 'text-lg font-semibold text-blue-400 mb-2' \n }, getSecurityFeaturesInfo(selectedType).title),\n React.createElement('p', { \n key: 'details-description', \n className: 'text-sm text-blue-300' \n }, getSecurityFeaturesInfo(selectedType).description)\n ]),\n\n // Available Features\n React.createElement('div', { key: 'available-features' }, [\n React.createElement('h4', {\n key: 'available-title',\n className: 'text-sm font-medium text-green-300 mb-3 flex items-center'\n }, [\n React.createElement('i', {\n key: 'check-icon',\n className: 'fas fa-check-circle mr-2'\n }),\n 'Available Security Features'\n ]),\n React.createElement('div', {\n key: 'available-list',\n className: 'grid grid-cols-1 gap-2'\n }, getSecurityFeaturesInfo(selectedType).available.map((feature, index) => \n React.createElement('div', {\n key: index,\n className: 'flex items-center gap-2 text-sm text-green-300'\n }, [\n React.createElement('i', {\n key: 'check',\n className: 'fas fa-check text-green-400 w-4'\n }),\n React.createElement('span', {\n key: 'text'\n }, feature)\n ])\n ))\n ]),\n\n // Unavailable Features (if any)\n getSecurityFeaturesInfo(selectedType).unavailable.length > 0 && React.createElement('div', { key: 'unavailable-features' }, [\n React.createElement('h4', {\n key: 'unavailable-title',\n className: 'text-sm font-medium text-red-300 mb-3 flex items-center'\n }, [\n React.createElement('i', {\n key: 'minus-icon',\n className: 'fas fa-minus-circle mr-2'\n }),\n 'Not Available in This Session'\n ]),\n React.createElement('div', {\n key: 'unavailable-list',\n className: 'grid grid-cols-1 gap-2'\n }, getSecurityFeaturesInfo(selectedType).unavailable.map((feature, index) => \n React.createElement('div', {\n key: index,\n className: 'flex items-center gap-2 text-sm text-red-300'\n }, [\n React.createElement('i', {\n key: 'minus',\n className: 'fas fa-minus text-red-400 w-4'\n }),\n React.createElement('span', {\n key: 'text'\n }, feature)\n ])\n ))\n ]),\n\n // Upgrade Information\n React.createElement('div', { key: 'upgrade-info' }, [\n React.createElement('h4', {\n key: 'upgrade-title',\n className: 'text-sm font-medium text-blue-300 mb-3 flex items-center'\n }, [\n React.createElement('i', {\n key: 'upgrade-icon',\n className: 'fas fa-arrow-up mr-2'\n }),\n 'Upgrade for More Security'\n ]),\n React.createElement('div', {\n key: 'upgrade-content',\n className: 'p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg'\n }, [\n React.createElement('div', {\n key: 'upgrade-next',\n className: 'text-sm font-medium text-blue-300 mb-2'\n }, getSecurityFeaturesInfo(selectedType).upgrade.next),\n React.createElement('div', {\n key: 'upgrade-features',\n className: 'grid grid-cols-1 gap-1'\n }, getSecurityFeaturesInfo(selectedType).upgrade.features.map((feature, index) => \n React.createElement('div', {\n key: index,\n className: 'flex items-center gap-2 text-xs text-blue-300'\n }, [\n React.createElement('i', {\n key: 'arrow',\n className: 'fas fa-arrow-right text-blue-400 w-3'\n }),\n React.createElement('span', {\n key: 'text'\n }, feature)\n ])\n ))\n ])\n ]),\n\n // Back Button\n React.createElement('div', { \n key: 'details-back-section', \n className: 'pt-4 border-t border-gray-600' \n }, [\n React.createElement('button', { \n key: 'details-back-btn',\n onClick: () => setStep('payment'),\n className: 'w-full bg-gray-600 hover:bg-gray-500 text-white py-2 px-4 rounded transition-colors'\n }, [\n React.createElement('i', { key: 'back-icon', className: 'fas fa-arrow-left mr-2' }),\n 'Back to Payment'\n ])\n ])\n ])\n ])\n ]);\n};\n\nwindow.PaymentModal = PaymentModal;", "const DownloadApps = () => {\r\n const apps = [\r\n { id: 'web', name: 'Web App', subtitle: 'Browser Version', icon: 'fas fa-globe', platform: 'Web', isActive: true, url: 'https://securebitchat.github.io/securebit-chat/', color: 'green' },\r\n { id: 'windows', name: 'Windows', subtitle: 'Desktop App', icon: 'fab fa-windows', platform: 'Desktop', isActive: false, url: '#', color: 'blue' },\r\n { id: 'macos', name: 'macOS', subtitle: 'Desktop App', icon: 'fab fa-apple', platform: 'Desktop', isActive: false, url: '#', color: 'gray' },\r\n { id: 'linux', name: 'Linux', subtitle: 'Desktop App', icon: 'fab fa-linux', platform: 'Desktop', isActive: false, url: '#', color: 'orange' },\r\n { id: 'ios', name: 'iOS', subtitle: 'iPhone & iPad', icon: 'fab fa-apple', platform: 'Mobile', isActive: false, url: 'https://apps.apple.com/app/securebit-chat/', color: 'blue' },\r\n { id: 'android', name: 'Android', subtitle: 'Google Play', icon: 'fab fa-android', platform: 'Mobile', isActive: false, url: 'https://play.google.com/store/apps/details?id=com.securebit.chat', color: 'green' }\r\n ];\r\n\r\n const handleDownload = (app) => {\r\n if (app.isActive) window.open(app.url, '_blank');\r\n };\r\n\r\n const desktopApps = apps.filter(a => a.platform !== 'Mobile');\r\n const mobileApps = apps.filter(a => a.platform === 'Mobile');\r\n\r\n const cardSize = \"w-28 h-28\"; \r\n\r\n return React.createElement('div', { className: \"mt-20 px-6\" }, [\r\n // Header\r\n React.createElement('div', { key: 'header', className: \"text-center max-w-3xl mx-auto mb-12\" }, [\r\n React.createElement('h3', { key: 'title', className: \"text-3xl font-bold text-primary mb-3\" }, 'Download SecureBit.chat'),\r\n React.createElement('p', { key: 'subtitle', className: \"text-secondary text-lg mb-5\" }, 'Stay secure on every device. Choose your platform and start chatting privately.')\r\n ]),\r\n\r\n React.createElement('div', { key: 'desktop-row', className: \"hidden sm:flex justify-center flex-wrap gap-6 mb-6\" },\r\n desktopApps.map(app =>\r\n React.createElement('div', {\r\n key: app.id,\r\n className: `group relative ${cardSize} rounded-2xl overflow-hidden card-minimal cursor-pointer`\r\n }, [\r\n React.createElement('i', {\r\n key: 'bg-icon',\r\n className: `${app.icon} absolute text-[3rem] text-white/10 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none transition-all duration-500 group-hover:scale-105`\r\n }),\r\n React.createElement('div', {\r\n key: 'overlay',\r\n className: \"absolute inset-0 bg-black/30 backdrop-blur-md flex flex-col items-center justify-center text-center opacity-0 transition-opacity duration-300 group-hover:opacity-100\"\r\n }, [\r\n React.createElement('h4', { key: 'name', className: `text-sm font-semibold text-primary mb-1` }, app.name),\r\n React.createElement('p', { key: 'subtitle', className: `text-xs text-secondary mb-2` }, app.subtitle),\r\n app.isActive ?\r\n React.createElement('button', {\r\n key: 'btn',\r\n onClick: () => handleDownload(app),\r\n className: `px-2 py-1 rounded-xl bg-emerald-500 text-black font-medium hover:bg-emerald-600 transition-colors text-xs`\r\n }, app.id === \"web\" ? \"Launch\" : \"Download\")\r\n :\r\n React.createElement('span', { key: 'coming', className: \"text-gray-400 font-medium text-xs\" }, \"Coming Soon\")\r\n ])\r\n ])\r\n )\r\n ),\r\n\r\n React.createElement('div', { key: 'mobile-row', className: \"flex justify-center gap-6\" },\r\n mobileApps.map(app =>\r\n React.createElement('div', {\r\n key: app.id,\r\n className: `group relative ${cardSize} rounded-2xl overflow-hidden card-minimal cursor-pointer`\r\n }, [\r\n React.createElement('i', {\r\n key: 'bg-icon',\r\n className: `${app.icon} absolute text-[3rem] text-white/10 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none transition-all duration-500 group-hover:scale-105`\r\n }),\r\n React.createElement('div', {\r\n key: 'overlay',\r\n className: \"absolute inset-0 bg-black/30 backdrop-blur-md flex flex-col items-center justify-center text-center opacity-0 transition-opacity duration-300 group-hover:opacity-100\"\r\n }, [\r\n React.createElement('h4', { key: 'name', className: `text-sm font-semibold text-primary mb-1` }, app.name),\r\n React.createElement('p', { key: 'subtitle', className: `text-xs text-secondary mb-2` }, app.subtitle),\r\n app.isActive ?\r\n React.createElement('button', {\r\n key: 'btn',\r\n onClick: () => handleDownload(app),\r\n className: `px-2 py-1 rounded-xl bg-emerald-500 text-black font-medium hover:bg-emerald-600 transition-colors text-xs`\r\n }, \"Download\")\r\n :\r\n React.createElement('span', { key: 'coming', className: \"text-gray-400 font-medium text-xs\" }, \"Coming Soon\")\r\n ])\r\n ])\r\n )\r\n )\r\n ]);\r\n};\r\n\r\nwindow.DownloadApps = DownloadApps;\r\n", "// File Transfer Component for Chat Interface - Fixed Version\r\nconst FileTransferComponent = ({ webrtcManager, isConnected }) => {\r\n const [dragOver, setDragOver] = React.useState(false);\r\n const [transfers, setTransfers] = React.useState({ sending: [], receiving: [] });\r\n const [readyFiles, setReadyFiles] = React.useState([]); // \u0444\u0430\u0439\u043B\u044B, \u0433\u043E\u0442\u043E\u0432\u044B\u0435 \u043A \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044E\r\n const fileInputRef = React.useRef(null);\r\n\r\n // Update transfers periodically\r\n React.useEffect(() => {\r\n if (!isConnected || !webrtcManager) return;\r\n\r\n const updateTransfers = () => {\r\n const currentTransfers = webrtcManager.getFileTransfers();\r\n setTransfers(currentTransfers);\r\n };\r\n\r\n const interval = setInterval(updateTransfers, 500);\r\n return () => clearInterval(interval);\r\n }, [isConnected, webrtcManager]);\r\n\r\n // Setup file transfer callbacks - \u0418\u0421\u041F\u0420\u0410\u0412\u041B\u0415\u041D\u0418\u0415: \u041D\u0415 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u043C \u043F\u0440\u043E\u043C\u0435\u0436\u0443\u0442\u043E\u0447\u043D\u044B\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u044F \u0432 \u0447\u0430\u0442\r\n React.useEffect(() => {\r\n if (!webrtcManager) return;\r\n\r\n webrtcManager.setFileTransferCallbacks(\r\n // Progress callback - \u0422\u041E\u041B\u042C\u041A\u041E \u043E\u0431\u043D\u043E\u0432\u043B\u044F\u0435\u043C UI, \u041D\u0415 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u043C \u0432 \u0447\u0430\u0442\r\n (progress) => {\r\n // \u041E\u0431\u043D\u043E\u0432\u043B\u044F\u0435\u043C \u0442\u043E\u043B\u044C\u043A\u043E \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u043E\u0435 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435\r\n const currentTransfers = webrtcManager.getFileTransfers();\r\n setTransfers(currentTransfers);\r\n \r\n // \u041D\u0415 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u043C \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u044F \u0432 \u0447\u0430\u0442!\r\n },\r\n \r\n // File received callback - \u0434\u043E\u0431\u0430\u0432\u043B\u044F\u0435\u043C \u043A\u043D\u043E\u043F\u043A\u0443 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044F \u0432 UI\r\n (fileData) => {\r\n // \u0414\u043E\u0431\u0430\u0432\u043B\u044F\u0435\u043C \u0432 \u0441\u043F\u0438\u0441\u043E\u043A \u0433\u043E\u0442\u043E\u0432\u044B\u0445 \u043A \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044E\r\n setReadyFiles(prev => {\r\n // \u0438\u0437\u0431\u0435\u0433\u0430\u0435\u043C \u0434\u0443\u0431\u043B\u0435\u0439 \u043F\u043E fileId\r\n if (prev.some(f => f.fileId === fileData.fileId)) return prev;\r\n return [...prev, {\r\n fileId: fileData.fileId,\r\n fileName: fileData.fileName,\r\n fileSize: fileData.fileSize,\r\n mimeType: fileData.mimeType,\r\n getBlob: fileData.getBlob,\r\n getObjectURL: fileData.getObjectURL,\r\n revokeObjectURL: fileData.revokeObjectURL\r\n }];\r\n });\r\n\r\n // \u041E\u0431\u043D\u043E\u0432\u043B\u044F\u0435\u043C \u0441\u043F\u0438\u0441\u043E\u043A \u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0445 \u043F\u0435\u0440\u0435\u0434\u0430\u0447\r\n const currentTransfers = webrtcManager.getFileTransfers();\r\n setTransfers(currentTransfers);\r\n },\r\n \r\n // Error callback\r\n (error) => {\r\n const currentTransfers = webrtcManager.getFileTransfers();\r\n setTransfers(currentTransfers);\r\n \r\n // \u0418\u0421\u041F\u0420\u0410\u0412\u041B\u0415\u041D\u0418\u0415: \u041D\u0415 \u0434\u0443\u0431\u043B\u0438\u0440\u0443\u0435\u043C \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u044F \u043E\u0431 \u043E\u0448\u0438\u0431\u043A\u0430\u0445\r\n // \u0423\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F \u043E\u0431 \u043E\u0448\u0438\u0431\u043A\u0430\u0445 \u0443\u0436\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u044E\u0442\u0441\u044F \u0432 WebRTC \u043C\u0435\u043D\u0435\u0434\u0436\u0435\u0440\u0435\r\n }\r\n );\r\n }, [webrtcManager]);\r\n\r\n const handleFileSelect = async (files) => {\r\n if (!isConnected || !webrtcManager) {\r\n alert('\u0421\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E. \u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435.');\r\n return;\r\n }\r\n\r\n // \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u044F \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u044F\r\n if (!webrtcManager.isConnected() || !webrtcManager.isVerified) {\r\n alert('\u0421\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u043D\u0435 \u0433\u043E\u0442\u043E\u0432\u043E \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043B\u043E\u0432. \u0414\u043E\u0436\u0434\u0438\u0442\u0435\u0441\u044C \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u044F.');\r\n return;\r\n }\r\n\r\n for (const file of files) {\r\n try {\r\n // \u041A\u0420\u0418\u0422\u0418\u0427\u0415\u0421\u041A\u041E\u0415 \u0418\u0421\u041F\u0420\u0410\u0412\u041B\u0415\u041D\u0418\u0415: \u0412\u0430\u043B\u0438\u0434\u0430\u0446\u0438\u044F \u0444\u0430\u0439\u043B\u0430 \u043F\u0435\u0440\u0435\u0434 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u043E\u0439\r\n const validation = webrtcManager.validateFile(file);\r\n if (!validation.isValid) {\r\n const errorMessage = validation.errors.join('. ');\r\n alert(`\u0424\u0430\u0439\u043B ${file.name} \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D: ${errorMessage}`);\r\n continue;\r\n }\r\n\r\n await webrtcManager.sendFile(file);\r\n } catch (error) {\r\n // \u0411\u043E\u043B\u0435\u0435 \u043C\u044F\u0433\u043A\u0430\u044F \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0430 \u043E\u0448\u0438\u0431\u043E\u043A - \u043D\u0435 \u0437\u0430\u043A\u0440\u044B\u0432\u0430\u0435\u043C \u0441\u0435\u0441\u0441\u0438\u044E\r\n \r\n // \u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044E \u043E\u0448\u0438\u0431\u043A\u0443, \u043D\u043E \u043D\u0435 \u0437\u0430\u043A\u0440\u044B\u0432\u0430\u0435\u043C \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435\r\n if (error.message.includes('Connection not ready')) {\r\n alert(`\u0424\u0430\u0439\u043B ${file.name} \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D \u0441\u0435\u0439\u0447\u0430\u0441. \u041F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u0438 \u043F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u0441\u043D\u043E\u0432\u0430.`);\r\n } else if (error.message.includes('File too large') || error.message.includes('exceeds maximum')) {\r\n alert(`\u0424\u0430\u0439\u043B ${file.name} \u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0431\u043E\u043B\u044C\u0448\u043E\u0439: ${error.message}`);\r\n } else if (error.message.includes('Maximum concurrent transfers')) {\r\n alert(`\u0414\u043E\u0441\u0442\u0438\u0433\u043D\u0443\u0442 \u043B\u0438\u043C\u0438\u0442 \u043E\u0434\u043D\u043E\u0432\u0440\u0435\u043C\u0435\u043D\u043D\u044B\u0445 \u043F\u0435\u0440\u0435\u0434\u0430\u0447. \u0414\u043E\u0436\u0434\u0438\u0442\u0435\u0441\u044C \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u0442\u0435\u043A\u0443\u0449\u0438\u0445 \u043F\u0435\u0440\u0435\u0434\u0430\u0447.`);\r\n } else if (error.message.includes('File type not allowed')) {\r\n alert(`\u0422\u0438\u043F \u0444\u0430\u0439\u043B\u0430 ${file.name} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F: ${error.message}`);\r\n } else {\r\n alert(`\u041E\u0448\u0438\u0431\u043A\u0430 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0438 \u0444\u0430\u0439\u043B\u0430 ${file.name}: ${error.message}`);\r\n }\r\n }\r\n }\r\n };\r\n\r\n const handleDrop = (e) => {\r\n e.preventDefault();\r\n setDragOver(false);\r\n \r\n const files = Array.from(e.dataTransfer.files);\r\n handleFileSelect(files);\r\n };\r\n\r\n const handleDragOver = (e) => {\r\n e.preventDefault();\r\n setDragOver(true);\r\n };\r\n\r\n const handleDragLeave = (e) => {\r\n e.preventDefault();\r\n setDragOver(false);\r\n };\r\n\r\n const handleFileInputChange = (e) => {\r\n const files = Array.from(e.target.files);\r\n handleFileSelect(files);\r\n e.target.value = ''; // Reset input\r\n };\r\n\r\n const formatFileSize = (bytes) => {\r\n if (bytes === 0) return '0 B';\r\n const k = 1024;\r\n const sizes = ['B', 'KB', 'MB', 'GB'];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\r\n };\r\n\r\n const getStatusIcon = (status) => {\r\n switch (status) {\r\n case 'metadata_sent':\r\n case 'preparing':\r\n return 'fas fa-cog fa-spin';\r\n case 'transmitting':\r\n case 'receiving':\r\n return 'fas fa-exchange-alt fa-pulse';\r\n case 'assembling':\r\n return 'fas fa-puzzle-piece fa-pulse';\r\n case 'completed':\r\n return 'fas fa-check text-green-400';\r\n case 'failed':\r\n return 'fas fa-times text-red-400';\r\n default:\r\n return 'fas fa-circle';\r\n }\r\n };\r\n\r\n const getStatusText = (status) => {\r\n switch (status) {\r\n case 'metadata_sent':\r\n return '\u041F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0430...';\r\n case 'transmitting':\r\n return '\u041E\u0442\u043F\u0440\u0430\u0432\u043A\u0430...';\r\n case 'receiving':\r\n return '\u041F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u0435...';\r\n case 'assembling':\r\n return '\u0421\u0431\u043E\u0440\u043A\u0430 \u0444\u0430\u0439\u043B\u0430...';\r\n case 'completed':\r\n return '\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E';\r\n case 'failed':\r\n return '\u041E\u0448\u0438\u0431\u043A\u0430';\r\n default:\r\n return status;\r\n }\r\n };\r\n\r\n if (!isConnected) {\r\n return React.createElement('div', {\r\n className: \"p-4 text-center text-muted\"\r\n }, '\u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u043E\u0432 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0430 \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0440\u0438 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u043E\u043C \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0438');\r\n }\r\n\r\n // \u041F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u043C \u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0435 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u044F\r\n const isConnectionReady = webrtcManager && webrtcManager.isConnected() && webrtcManager.isVerified;\r\n \r\n if (!isConnectionReady) {\r\n return React.createElement('div', {\r\n className: \"p-4 text-center text-yellow-600\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: 'fas fa-exclamation-triangle mr-2'\r\n }),\r\n '\u0421\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u0435 \u0443\u0441\u0442\u0430\u043D\u0430\u0432\u043B\u0438\u0432\u0430\u0435\u0442\u0441\u044F... \u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u043E\u0432 \u0431\u0443\u0434\u0435\u0442 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0430 \u043F\u043E\u0441\u043B\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438.'\r\n ]);\r\n }\r\n\r\n return React.createElement('div', {\r\n className: \"file-transfer-component\"\r\n }, [\r\n // File Drop Zone\r\n React.createElement('div', {\r\n key: 'drop-zone',\r\n className: `file-drop-zone ${dragOver ? 'drag-over' : ''}`,\r\n onDrop: handleDrop,\r\n onDragOver: handleDragOver,\r\n onDragLeave: handleDragLeave,\r\n onClick: () => fileInputRef.current?.click()\r\n }, [\r\n React.createElement('div', {\r\n key: 'drop-content',\r\n className: \"drop-content\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: 'fas fa-cloud-upload-alt text-2xl mb-2 text-blue-400'\r\n }),\r\n React.createElement('p', {\r\n key: 'text',\r\n className: \"text-primary font-medium\"\r\n }, 'Drag files here or click to select'),\r\n React.createElement('p', {\r\n key: 'subtext',\r\n className: \"text-muted text-sm\"\r\n }, 'Maximum size: 100 MB per file')\r\n ])\r\n ]),\r\n\r\n // Hidden file input\r\n React.createElement('input', {\r\n key: 'file-input',\r\n ref: fileInputRef,\r\n type: 'file',\r\n multiple: true,\r\n className: 'hidden',\r\n onChange: handleFileInputChange\r\n }),\r\n\r\n // Active Transfers\r\n (transfers.sending.length > 0 || transfers.receiving.length > 0) && React.createElement('div', {\r\n key: 'transfers',\r\n className: \"active-transfers mt-4\"\r\n }, [\r\n React.createElement('h4', {\r\n key: 'title',\r\n className: \"text-primary font-medium mb-3 flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: 'fas fa-exchange-alt mr-2'\r\n }),\r\n '\u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u043E\u0432'\r\n ]),\r\n\r\n // Sending files\r\n ...transfers.sending.map(transfer => \r\n React.createElement('div', {\r\n key: `send-${transfer.fileId}`,\r\n className: \"transfer-item bg-blue-500/10 border border-blue-500/20 rounded-lg p-3 mb-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"flex items-center justify-between mb-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'info',\r\n className: \"flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: 'fas fa-upload text-blue-400 mr-2'\r\n }),\r\n React.createElement('span', {\r\n key: 'name',\r\n className: \"text-primary font-medium text-sm\"\r\n }, transfer.fileName),\r\n React.createElement('span', {\r\n key: 'size',\r\n className: \"text-muted text-xs ml-2\"\r\n }, formatFileSize(transfer.fileSize))\r\n ]),\r\n React.createElement('button', {\r\n key: 'cancel',\r\n onClick: () => webrtcManager.cancelFileTransfer(transfer.fileId),\r\n className: \"text-red-400 hover:text-red-300 text-xs\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-times'\r\n })\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'progress',\r\n className: \"progress-bar\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'fill',\r\n className: \"progress-fill bg-blue-400\",\r\n style: { width: `${transfer.progress}%` }\r\n }),\r\n React.createElement('div', {\r\n key: 'text',\r\n className: \"progress-text text-xs flex items-center justify-between\"\r\n }, [\r\n React.createElement('span', {\r\n key: 'status',\r\n className: \"flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: `${getStatusIcon(transfer.status)} mr-1`\r\n }),\r\n getStatusText(transfer.status)\r\n ]),\r\n React.createElement('span', {\r\n key: 'percent'\r\n }, `${transfer.progress.toFixed(1)}%`)\r\n ])\r\n ])\r\n ])\r\n ),\r\n\r\n // Receiving files\r\n ...transfers.receiving.map(transfer => \r\n React.createElement('div', {\r\n key: `recv-${transfer.fileId}`,\r\n className: \"transfer-item bg-green-500/10 border border-green-500/20 rounded-lg p-3 mb-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"flex items-center justify-between mb-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'info',\r\n className: \"flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: 'fas fa-download text-green-400 mr-2'\r\n }),\r\n React.createElement('span', {\r\n key: 'name',\r\n className: \"text-primary font-medium text-sm\"\r\n }, transfer.fileName),\r\n React.createElement('span', {\r\n key: 'size',\r\n className: \"text-muted text-xs ml-2\"\r\n }, formatFileSize(transfer.fileSize))\r\n ]),\r\n React.createElement('div', { key: 'actions', className: 'flex items-center space-x-2' }, [\r\n (() => {\r\n const rf = readyFiles.find(f => f.fileId === transfer.fileId);\r\n if (!rf || transfer.status !== 'completed') return null;\r\n return React.createElement('button', {\r\n key: 'download',\r\n className: 'text-green-400 hover:text-green-300 text-xs flex items-center',\r\n onClick: async () => {\r\n try {\r\n const url = await rf.getObjectURL();\r\n const a = document.createElement('a');\r\n a.href = url;\r\n a.download = rf.fileName || 'file';\r\n a.click();\r\n rf.revokeObjectURL(url);\r\n } catch (e) {\r\n alert('Failed to start download: ' + e.message);\r\n }\r\n }\r\n }, [\r\n React.createElement('i', { key: 'i', className: 'fas fa-download mr-1' }),\r\n 'Download'\r\n ]);\r\n })(),\r\n React.createElement('button', {\r\n key: 'cancel',\r\n onClick: () => webrtcManager.cancelFileTransfer(transfer.fileId),\r\n className: \"text-red-400 hover:text-red-300 text-xs\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-times'\r\n })\r\n ])\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'progress',\r\n className: \"progress-bar\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'fill',\r\n className: \"progress-fill bg-green-400\",\r\n style: { width: `${transfer.progress}%` }\r\n }),\r\n React.createElement('div', {\r\n key: 'text',\r\n className: \"progress-text text-xs flex items-center justify-between\"\r\n }, [\r\n React.createElement('span', {\r\n key: 'status',\r\n className: \"flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: `${getStatusIcon(transfer.status)} mr-1`\r\n }),\r\n getStatusText(transfer.status)\r\n ]),\r\n React.createElement('span', {\r\n key: 'percent'\r\n }, `${transfer.progress.toFixed(1)}%`)\r\n ])\r\n ])\r\n ])\r\n )\r\n ])\r\n ]);\r\n};\r\n\r\n// Export\r\nwindow.FileTransferComponent = FileTransferComponent;", "import { EnhancedSecureCryptoUtils } from '../crypto/EnhancedSecureCryptoUtils.js';\r\nimport { EnhancedSecureWebRTCManager } from '../network/EnhancedSecureWebRTCManager.js';\r\nimport { PayPerSessionManager } from '../session/PayPerSessionManager.js';\r\nimport { EnhancedSecureFileTransfer } from '../transfer/EnhancedSecureFileTransfer.js';\r\n\r\n// Import UI components (side-effect: they attach themselves to window.*)\r\nimport '../components/ui/SessionTimer.jsx';\r\nimport '../components/ui/Header.jsx';\r\nimport '../components/ui/SessionTypeSelector.jsx';\r\nimport '../components/ui/LightningPayment.jsx';\r\nimport '../components/ui/PaymentModal.jsx';\r\nimport '../components/ui/DownloadApps.jsx';\r\nimport '../components/ui/FileTransfer.jsx';\r\n\r\n// Expose to global for legacy usage inside app code\r\nwindow.EnhancedSecureCryptoUtils = EnhancedSecureCryptoUtils;\r\nwindow.EnhancedSecureWebRTCManager = EnhancedSecureWebRTCManager;\r\nwindow.PayPerSessionManager = PayPerSessionManager;\r\nwindow.EnhancedSecureFileTransfer = EnhancedSecureFileTransfer;\r\n\r\n// Mount application once DOM and modules are ready\r\nconst start = () => {\r\n if (typeof window.initializeApp === 'function') {\r\n window.initializeApp();\r\n } else if (window.DEBUG_MODE) {\r\n console.error('initializeApp is not defined on window');\r\n }\r\n};\r\n\r\nif (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', start);\r\n} else {\r\n start();\r\n}\r\n"], + "mappings": "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", + "names": ["fileMessageTypes", "attempts", "start", "start", "attempts", "chunk", "fileMessageTypes", "window", "start", "cryptoValid", "securityLevel", "webrtcManager", "React", "React", "useState", "useEffect", "error"] +} diff --git a/dist/app.js b/dist/app.js new file mode 100644 index 0000000..e304728 --- /dev/null +++ b/dist/app.js @@ -0,0 +1,3176 @@ +// src/app.jsx +var UniqueFeatureSlider = () => { + const [currentSlide, setCurrentSlide] = React.useState(0); + const slides = [ + { + icon: "fas fa-shield-halved", + color: "orange", + title: "18-Layer Military Security", + description: "Revolutionary defense system with ECDH P-384 + AES-GCM 256 + ECDSA + Complete ASN.1 Validation. Enhanced Security Edition provides military-grade protection exceeding government standards with complete key structure verification." + }, + { + icon: "fas fa-bolt", + color: "yellow", + title: "Lightning Network Payments", + description: "First messenger with Lightning Network integration. Pay-per-session with satoshis via WebLN. Sustainable economic model without ads or data harvesting." + }, + { + icon: "fas fa-network-wired", + color: "purple", + title: "Pure P2P WebRTC Architecture", + description: "Direct peer-to-peer connections without any servers. Impossible to censor, block, or monitor. Complete decentralization with zero infrastructure." + }, + { + icon: "fas fa-sync-alt", + color: "green", + title: "Perfect Forward Secrecy", + description: "Automatic key rotation every 5 minutes or 100 messages. Non-extractable keys with hardware protection ensure past messages remain secure." + }, + { + icon: "fas fa-user-secret", + color: "cyan", + title: "Advanced Traffic Obfuscation", + description: "Fake traffic generation, packet padding, and pattern masking make communication indistinguishable from random noise. Defeats traffic analysis." + }, + { + icon: "fas fa-eye-slash", + color: "blue", + title: "Zero Data Collection", + description: "No registration, no servers, no logs. Messages exist only in browser memory. Complete anonymity with instant anonymous channels." + }, + { + icon: "fas fa-code", + color: "emerald", + title: "100% Open Source Security", + description: "All code is open for audit under MIT license. Uses only standard WebCrypto APIs. Cryptography runs directly in browser without server dependencies." + } + ]; + const nextSlide = () => setCurrentSlide((prev) => (prev + 1) % slides.length); + const prevSlide = () => setCurrentSlide((prev) => (prev - 1 + slides.length) % slides.length); + const goToSlide = (index) => setCurrentSlide(index); + React.useEffect(() => { + const timer = setInterval(() => { + nextSlide(); + }, 15e3); + return () => clearInterval(timer); + }, []); + return React.createElement("div", { + className: "mt-12" + }, [ + React.createElement("div", { + key: "header", + className: "text-center mb-8" + }, [ + React.createElement("h3", { + key: "title", + className: "text-2xl font-semibold text-primary mb-3" + }, "Why SecureBit.chat is unique"), + React.createElement("p", { + key: "subtitle", + className: "text-secondary max-w-2xl mx-auto" + }, "The only messenger with military-grade cryptography and Lightning payments") + ]), + React.createElement("div", { + key: "slider-container", + className: "relative max-w-4xl mx-auto" + }, [ + React.createElement("div", { + key: "slider-wrapper", + className: "overflow-hidden rounded-xl" + }, [ + React.createElement("div", { + key: "slides", + className: "flex transition-transform duration-500 ease-in-out", + style: { transform: `translateX(-${currentSlide * 100}%)` } + }, slides.map( + (slide, index) => React.createElement("div", { + key: index, + className: "w-full flex-shrink-0 px-4" + }, [ + React.createElement("div", { + key: "slide-content", + className: "card-minimal rounded-xl p-8 text-center min-h-[300px] flex flex-col justify-center relative overflow-hidden" + }, [ + // Background icon + React.createElement("i", { + key: "bg-icon", + className: `${slide.icon} absolute right-[-100px] top-1/2 -translate-y-1/2 opacity-10 text-[300px] pointer-events-none ${slide.color === "orange" ? "text-orange-500" : slide.color === "yellow" ? "text-yellow-500" : slide.color === "purple" ? "text-purple-500" : slide.color === "green" ? "text-green-500" : slide.color === "cyan" ? "text-cyan-500" : slide.color === "blue" ? "text-blue-500" : "text-emerald-500"}` + }), + // Content + React.createElement("h4", { + key: "slide-title", + className: "text-xl font-semibold text-primary mb-4 relative z-10" + }, slide.title), + React.createElement("p", { + key: "slide-description", + className: "text-secondary leading-relaxed max-w-2xl mx-auto relative z-10" + }, slide.description) + ]) + ]) + )) + ]), + // Navigation + React.createElement("button", { + key: "prev-btn", + onClick: prevSlide, + className: "absolute left-2 top-1/2 transform -translate-y-1/2 w-10 h-10 bg-gray-600/80 hover:bg-gray-500/80 text-white rounded-full flex items-center justify-center transition-all duration-200 z-10" + }, [ + React.createElement("i", { + key: "prev-icon", + className: "fas fa-chevron-left" + }) + ]), + React.createElement("button", { + key: "next-btn", + onClick: nextSlide, + className: "absolute right-2 top-1/2 transform -translate-y-1/2 w-10 h-10 bg-gray-600/80 hover:bg-gray-500/80 text-white rounded-full flex items-center justify-center transition-all duration-200 z-10" + }, [ + React.createElement("i", { + key: "next-icon", + className: "fas fa-chevron-right" + }) + ]) + ]), + // Enhanced dots navigation (оставляем улучшенные точки) + React.createElement("div", { + key: "dots-container", + className: "flex justify-center space-x-3 mt-6" + }, slides.map( + (slide, index) => React.createElement("button", { + key: index, + onClick: () => goToSlide(index), + className: `relative group transition-all duration-300 ${index === currentSlide ? "w-12 h-4 bg-orange-500 rounded-full" : "w-4 h-4 bg-gray-600 hover:bg-gray-500 rounded-full hover:scale-125"}` + }, [ + // Tooltip on hover + React.createElement("div", { + key: "tooltip", + className: "absolute -top-10 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white text-xs px-2 py-1 rounded opacity-0 group-hover:opacity-100 transition-opacity duration-200 whitespace-nowrap pointer-events-none" + }, slide.title) + ]) + )) + ]); +}; +var ComparisonTable = () => { + const [selectedFeature, setSelectedFeature] = React.useState(null); + const messengers = [ + { + name: "SecureBit.chat", + logo: /* @__PURE__ */ React.createElement("div", { className: "w-8 h-8 bg-orange-500/10 border border-orange-500/20 rounded-lg flex items-center justify-center" }, /* @__PURE__ */ React.createElement("i", { className: "fas fa-shield-halved text-orange-400" })), + type: "P2P WebRTC", + version: "Latest", + color: "orange" + }, + { + name: "Signal", + logo: /* @__PURE__ */ React.createElement("svg", { className: "w-8 h-8", viewBox: "0 0 122.88 122.31", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React.createElement("path", { className: "fill-blue-500", d: "M27.75,0H95.13a27.83,27.83,0,0,1,27.75,27.75V94.57a27.83,27.83,0,0,1-27.75,27.74H27.75A27.83,27.83,0,0,1,0,94.57V27.75A27.83,27.83,0,0,1,27.75,0Z" }), /* @__PURE__ */ React.createElement("path", { className: "fill-white", d: "M61.44,25.39A35.76,35.76,0,0,0,31.18,80.18L27.74,94.86l14.67-3.44a35.77,35.77,0,1,0,19-66Z" })), + type: "Centralized", + version: "Latest", + color: "blue" + }, + { + name: "Threema", + logo: /* @__PURE__ */ React.createElement("svg", { className: "w-8 h-8", viewBox: "0 0 122.88 122.88", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React.createElement("rect", { width: "122.88", height: "122.88", rx: "18.43", fill: "#474747" }), /* @__PURE__ */ React.createElement("path", { fill: "#FFFFFF", d: "M44.26,78.48l-19.44,4.8l4.08-16.56c-4.08-5.28-6.48-12-6.48-18.96c0-18.96,17.52-34.32,39.12-34.32c21.6,0,39.12,15.36,39.12,34.32c0,18.96-17.52,34.32-39.12,34.32c-6,0-12-1.2-17.04-3.36L44.26,78.48z M50.26,44.64h-0.48c-0.96,0-1.68,0.72-1.44,1.68v15.6c0,0.96,0.72,1.68,1.68,1.68l23.04,0c0.96,0,1.68-0.72,1.68-1.68v-15.6c0-0.96-0.72-1.68-1.68-1.68h-0.48v-4.32c0-6-5.04-11.04-11.04-11.04S50.5,34.32,50.5,40.32v4.32H50.26z M68.02,44.64h-13.2v-4.32c0-3.6,2.88-6.72,6.72-6.72c3.6,0,6.72,2.88,6.72,6.72v4.32H68.02z" }), /* @__PURE__ */ React.createElement("circle", { cx: "37.44", cy: "97.44", r: "6.72", fill: "#3fe669" }), /* @__PURE__ */ React.createElement("circle", { cx: "61.44", cy: "97.44", r: "6.72", fill: "#3fe669" }), /* @__PURE__ */ React.createElement("circle", { cx: "85.44", cy: "97.44", r: "6.72", fill: "#3fe669" })), + type: "Centralized", + version: "Latest", + color: "green" + }, + { + name: "Session", + logo: /* @__PURE__ */ React.createElement("svg", { className: "w-8 h-8", viewBox: "0 0 1024 1024", xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React.createElement("rect", { width: "1024", height: "1024", fill: "#333132" }), /* @__PURE__ */ React.createElement("path", { fill: "#00f782", d: "M431 574.8c-.8-7.4-6.7-8.2-10.8-10.6-13.6-7.9-27.5-15.4-41.3-23l-22.5-12.3c-8.5-4.7-17.1-9.2-25.6-14.1-10.5-6-21-11.9-31.1-18.6-18.9-12.5-33.8-29.1-46.3-48.1-8.3-12.6-14.8-26.1-19.2-40.4-6.7-21.7-10.8-44.1-7.8-66.8 1.8-14 4.6-28 9.7-41.6 7.8-20.8 19.3-38.8 34.2-54.8 9.8-10.6 21.2-19.1 33.4-26.8 14.7-9.3 30.7-15.4 47.4-19 13.8-3 28.1-4.3 42.2-4.4 89.9-.4 179.7-.3 269.6 0 12.6 0 25.5 1 37.7 4.1 24.3 6.2 45.7 18.2 63 37 11.2 12.2 20.4 25.8 25.8 41.2 7.3 20.7 12.3 42.1 6.7 64.4-2.1 8.5-2.7 17.5-6.1 25.4-4.7 10.9-10.8 21.2-17.2 31.2-8.7 13.5-20.5 24.3-34.4 32.2-10.1 5.7-21 10.2-32 14.3-18.1 6.7-37.2 5-56.1 5.2-17.2.2-34.5 0-51.7.1-1.7 0-3.4 1.2-5.1 1.9 1.3 1.8 2.1 4.3 3.9 5.3 13.5 7.8 27.2 15.4 40.8 22.9 11 6 22.3 11.7 33.2 17.9 15.2 8.5 30.2 17.4 45.3 26.1 19.3 11.1 34.8 26.4 47.8 44.3 9.7 13.3 17.2 27.9 23 43.5 6.1 16.6 9.2 33.8 10.4 51.3.6 9.1-.7 18.5-1.9 27.6-1.2 9.1-2.7 18.4-5.6 27.1-3.3 10.2-7.4 20.2-12.4 29.6-8.4 15.7-19.6 29.4-32.8 41.4-12.7 11.5-26.8 20.6-42.4 27.6-22.9 10.3-46.9 14.4-71.6 14.5-89.7.3-179.4.2-269.1-.1-12.6 0-25.5-1-37.7-3.9-24.5-5.7-45.8-18-63.3-36.4-11.6-12.3-20.2-26.5-26.6-41.9-2.7-6.4-4.1-13.5-5.4-20.4-1.5-8.1-2.8-16.3-3.1-24.5-.6-15.7 2.8-30.9 8.2-45.4 8.2-22 21.7-40.6 40.2-55.2 10-7.9 21.3-13.7 33.1-18.8 16.6-7.2 34-8.1 51.4-8.5 21.9-.5 43.9-.1 65.9-.1 1.9-.1 3.9-.3 6.2-.4zm96.3-342.4c0 .1 0 .1 0 0-48.3.1-96.6-.6-144.9.5-13.5.3-27.4 3.9-40.1 8.7-14.9 5.6-28.1 14.6-39.9 25.8-20.2 19-32.2 42.2-37.2 68.9-3.6 19-1.4 38.1 4.1 56.5 4.1 13.7 10.5 26.4 18.5 38.4 14.8 22.2 35.7 36.7 58.4 49.2 11 6.1 22.2 11.9 33.2 18 13.5 7.5 26.9 15.1 40.4 22.6 13.1 7.3 26.2 14.5 39.2 21.7 9.7 5.3 19.4 10.7 29.1 16.1 2.9 1.6 4.1.2 4.5-2.4.3-2 .3-4 .3-6.1v-58.8c0-19.9.1-39.9 0-59.8 0-6.6 1.7-12.8 7.6-16.1 3.5-2 8.2-2.8 12.4-2.8 50.3-.2 100.7-.2 151-.1 19.8 0 38.3-4.4 55.1-15.1 23.1-14.8 36.3-36.3 40.6-62.9 3.4-20.8-1-40.9-12.4-58.5-17.8-27.5-43.6-43-76.5-43.6-47.8-.8-95.6-.2-143.4-.2zm-30.6 559.7c45.1 0 90.2-.2 135.3.1 18.9.1 36.6-3.9 53.9-11.1 18.4-7.7 33.6-19.8 46.3-34.9 9.1-10.8 16.2-22.9 20.8-36.5 4.2-12.4 7.4-24.7 7.3-37.9-.1-10.3.2-20.5-3.4-30.5-2.6-7.2-3.4-15.2-6.4-22.1-3.9-8.9-8.9-17.3-14-25.5-12.9-20.8-31.9-34.7-52.8-46.4-10.6-5.9-21.2-11.6-31.8-17.5-10.3-5.7-20.4-11.7-30.7-17.4-11.2-6.1-22.5-11.9-33.7-18-16.6-9.1-33.1-18.4-49.8-27.5-4.9-2.7-6.1-1.9-6.4 3.9-.1 2-.1 4.1-.1 6.1v114.5c0 14.8-5.6 20.4-20.4 20.4-47.6.1-95.3-.1-142.9.2-10.5.1-21.1 1.4-31.6 2.8-16.5 2.2-30.5 9.9-42.8 21-17 15.5-27 34.7-29.4 57.5-1.1 10.9-.4 21.7 2.9 32.5 3.7 12.3 9.2 23.4 17.5 33 19.2 22.1 43.4 33.3 72.7 33.3 46.6.1 93 0 139.5 0z" })), + type: "Onion Network", + version: "Latest", + color: "cyan" + } + ]; + const features = [ + { + name: "Security Architecture", + lockbit: { status: "\u{1F3C6}", detail: "18-layer military-grade defense system with complete ASN.1 validation" }, + signal: { status: "\u2705", detail: "Signal Protocol with double ratchet" }, + threema: { status: "\u2705", detail: "Standard security implementation" }, + session: { status: "\u2705", detail: "Modified Signal Protocol + Onion routing" } + }, + { + name: "Cryptography", + lockbit: { status: "\u{1F3C6}", detail: "ECDH P-384 + AES-GCM 256 + ECDSA P-384" }, + signal: { status: "\u2705", detail: "Signal Protocol + Double Ratchet" }, + threema: { status: "\u2705", detail: "NaCl + XSalsa20 + Poly1305" }, + session: { status: "\u2705", detail: "Modified Signal Protocol" } + }, + { + name: "Perfect Forward Secrecy", + lockbit: { status: "\u{1F3C6}", detail: "Auto rotation every 5 minutes or 100 messages" }, + signal: { status: "\u2705", detail: "Double Ratchet algorithm" }, + threema: { status: "\u26A0\uFE0F", detail: "Partial (group chats)" }, + session: { status: "\u2705", detail: "Session Ratchet algorithm" } + }, + { + name: "Architecture", + lockbit: { status: "\u{1F3C6}", detail: "Pure P2P WebRTC without servers" }, + signal: { status: "\u274C", detail: "Centralized Signal servers" }, + threema: { status: "\u274C", detail: "Threema servers in Switzerland" }, + session: { status: "\u26A0\uFE0F", detail: "Onion routing via network nodes" } + }, + { + name: "Registration Anonymity", + lockbit: { status: "\u{1F3C6}", detail: "No registration required, instant anonymous channels" }, + signal: { status: "\u274C", detail: "Phone number required" }, + threema: { status: "\u2705", detail: "ID generated locally" }, + session: { status: "\u2705", detail: "Random session ID" } + }, + { + name: "Payment Integration", + lockbit: { status: "\u{1F3C6}", detail: "Lightning Network satoshis per session + WebLN" }, + signal: { status: "\u274C", detail: "No payment system" }, + threema: { status: "\u274C", detail: "No payment system" }, + session: { status: "\u274C", detail: "No payment system" } + }, + { + name: "Metadata Protection", + lockbit: { status: "\u{1F3C6}", detail: "Full metadata encryption + traffic obfuscation" }, + signal: { status: "\u26A0\uFE0F", detail: "Sealed Sender (partial)" }, + threema: { status: "\u26A0\uFE0F", detail: "Minimal metadata" }, + session: { status: "\u2705", detail: "Onion routing hides metadata" } + }, + { + name: "Traffic Obfuscation", + lockbit: { status: "\u{1F3C6}", detail: "Fake traffic + pattern masking + packet padding" }, + signal: { status: "\u274C", detail: "No traffic obfuscation" }, + threema: { status: "\u274C", detail: "No traffic obfuscation" }, + session: { status: "\u2705", detail: "Onion routing provides obfuscation" } + }, + { + name: "Open Source", + lockbit: { status: "\u{1F3C6}", detail: "100% open + auditable + MIT license" }, + signal: { status: "\u2705", detail: "Fully open" }, + threema: { status: "\u26A0\uFE0F", detail: "Only clients open" }, + session: { status: "\u2705", detail: "Fully open" } + }, + { + name: "MITM Protection", + lockbit: { status: "\u{1F3C6}", detail: "Out-of-band verification + mutual auth + ECDSA" }, + signal: { status: "\u2705", detail: "Safety numbers verification" }, + threema: { status: "\u2705", detail: "QR code scanning" }, + session: { status: "\u26A0\uFE0F", detail: "Basic key verification" } + }, + { + name: "Economic Model", + lockbit: { status: "\u{1F3C6}", detail: "Sustainable pay-per-session model" }, + signal: { status: "\u26A0\uFE0F", detail: "Donations and grants dependency" }, + threema: { status: "\u2705", detail: "One-time app purchase" }, + session: { status: "\u26A0\uFE0F", detail: "Donations dependency" } + }, + { + name: "Censorship Resistance", + lockbit: { status: "\u{1F3C6}", detail: "Impossible to block P2P + no servers to target" }, + signal: { status: "\u26A0\uFE0F", detail: "Blocked in authoritarian countries" }, + threema: { status: "\u26A0\uFE0F", detail: "May be blocked" }, + session: { status: "\u2705", detail: "Onion routing bypasses blocks" } + }, + { + name: "Data Storage", + lockbit: { status: "\u{1F3C6}", detail: "Zero data storage - only in browser memory" }, + signal: { status: "\u26A0\uFE0F", detail: "Local database storage" }, + threema: { status: "\u26A0\uFE0F", detail: "Local + optional backup" }, + session: { status: "\u26A0\uFE0F", detail: "Local database storage" } + }, + { + name: "Key Security", + lockbit: { status: "\u{1F3C6}", detail: "Non-extractable keys + hardware protection" }, + signal: { status: "\u2705", detail: "Secure key storage" }, + threema: { status: "\u2705", detail: "Local key storage" }, + session: { status: "\u2705", detail: "Secure key storage" } + }, + { + name: "Post-Quantum Roadmap", + lockbit: { status: "\u2705", detail: "Planned v5.0 - CRYSTALS-Kyber/Dilithium" }, + signal: { status: "\u26A0\uFE0F", detail: "PQXDH in development" }, + threema: { status: "\u274C", detail: "Not announced" }, + session: { status: "\u274C", detail: "Not announced" } + } + ]; + const getStatusIcon = (status) => { + const statusMap = { + "\u{1F3C6}": { icon: "\u{1F3C6}", color: "text-yellow-400" }, + "\u2705": { icon: "\u2705", color: "text-green-400" }, + "\u26A0\uFE0F": { icon: "\u26A0\uFE0F", color: "text-yellow-400" }, + "\u274C": { icon: "\u274C", color: "text-red-400" } + }; + return statusMap[status] || { icon: status, color: "text-gray-400" }; + }; + const toggleFeatureDetail = (index) => { + setSelectedFeature(selectedFeature === index ? null : index); + }; + return /* @__PURE__ */ React.createElement("div", { className: "mt-16" }, /* @__PURE__ */ React.createElement("div", { className: "text-center mb-8" }, /* @__PURE__ */ React.createElement("h3", { className: "text-3xl font-bold text-primary mb-3" }, "Enhanced Security Edition Comparison"), /* @__PURE__ */ React.createElement("p", { className: "text-secondary max-w-2xl mx-auto mb-4" }, "Enhanced Security Edition vs leading secure messengers"), /* @__PURE__ */ React.createElement("div", { className: "inline-flex items-center px-4 py-2 bg-yellow-500/10 border border-yellow-500/20 rounded-lg" }, /* @__PURE__ */ React.createElement("span", { className: "text-yellow-400 mr-2" }, "\u{1F3C6}"), /* @__PURE__ */ React.createElement("span", { className: "text-yellow-300 text-sm font-medium" }, "Category Leader - Military-Grade Security"))), /* @__PURE__ */ React.createElement("div", { className: "max-w-7xl mx-auto" }, /* @__PURE__ */ React.createElement("div", { className: "md:hidden p-4 bg-yellow-500/10 border border-yellow-500/20 rounded-lg mb-4" }, /* @__PURE__ */ React.createElement("p", { className: "text-yellow-400 text-sm text-center" }, "\u{1F4A1} Rotate your device horizontally for better viewing")), /* @__PURE__ */ React.createElement("div", { className: "overflow-x-auto custom-scrollbar" }, /* @__PURE__ */ React.createElement( + "table", + { + className: "w-full border-collapse rounded-xl overflow-hidden shadow-2xl", + style: { backgroundColor: "rgba(42, 43, 42, 0.9)" } + }, + /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement("tr", { className: "bg-my" }, /* @__PURE__ */ React.createElement("th", { className: "text-left p-4 border-b border-gray-600 text-primary font-bold min-w-[240px]" }, "Security Criterion"), messengers.map((messenger, index) => /* @__PURE__ */ React.createElement("th", { key: `messenger-${index}`, className: "text-center p-4 border-b border-gray-600 min-w-[160px]" }, /* @__PURE__ */ React.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ React.createElement("div", { className: "mb-2" }, messenger.logo), /* @__PURE__ */ React.createElement("div", { className: `text-sm font-bold ${messenger.color === "orange" ? "text-orange-400" : messenger.color === "blue" ? "text-blue-400" : messenger.color === "green" ? "text-green-400" : "text-cyan-400"}` }, messenger.name), /* @__PURE__ */ React.createElement("div", { className: "text-xs text-gray-400" }, messenger.type), /* @__PURE__ */ React.createElement("div", { className: "text-xs text-gray-500 mt-1" }, messenger.version)))))), + /* @__PURE__ */ React.createElement("tbody", null, features.map((feature, featureIndex) => /* @__PURE__ */ React.createElement(React.Fragment, { key: `feature-${featureIndex}` }, /* @__PURE__ */ React.createElement( + "tr", + { + className: `border-b border-gray-700/30 hover:bg-gray-800/30 transition-all duration-200 cursor-pointer ${selectedFeature === featureIndex ? "bg-gray-800/50" : ""}`, + onClick: () => toggleFeatureDetail(featureIndex) + }, + /* @__PURE__ */ React.createElement("td", { className: "p-4 text-primary font-semibold" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React.createElement("span", null, feature.name), /* @__PURE__ */ React.createElement("i", { className: `fas fa-chevron-${selectedFeature === featureIndex ? "up" : "down"} text-xs text-gray-400 opacity-60 transition-all duration-200` }))), + /* @__PURE__ */ React.createElement("td", { className: "p-4 text-center" }, /* @__PURE__ */ React.createElement("span", { className: `${getStatusIcon(feature.lockbit.status).color} text-2xl` }, getStatusIcon(feature.lockbit.status).icon)), + /* @__PURE__ */ React.createElement("td", { className: "p-4 text-center" }, /* @__PURE__ */ React.createElement("span", { className: `${getStatusIcon(feature.signal.status).color} text-2xl` }, getStatusIcon(feature.signal.status).icon)), + /* @__PURE__ */ React.createElement("td", { className: "p-4 text-center" }, /* @__PURE__ */ React.createElement("span", { className: `${getStatusIcon(feature.threema.status).color} text-2xl` }, getStatusIcon(feature.threema.status).icon)), + /* @__PURE__ */ React.createElement("td", { className: "p-4 text-center" }, /* @__PURE__ */ React.createElement("span", { className: `${getStatusIcon(feature.session.status).color} text-2xl` }, getStatusIcon(feature.session.status).icon)) + ), selectedFeature === featureIndex && /* @__PURE__ */ React.createElement("tr", { className: "border-b border-gray-700/30 bg-gradient-to-r from-gray-800/20 to-gray-900/20" }, /* @__PURE__ */ React.createElement("td", { className: "p-4 text-xs text-gray-400 font-medium" }, "Technical Details:"), /* @__PURE__ */ React.createElement("td", { className: "p-4 text-center" }, /* @__PURE__ */ React.createElement("div", { className: "text-xs text-orange-300 font-medium leading-relaxed max-w-32" }, feature.lockbit.detail)), /* @__PURE__ */ React.createElement("td", { className: "p-4 text-center" }, /* @__PURE__ */ React.createElement("div", { className: "text-xs text-blue-300 leading-relaxed max-w-32" }, feature.signal.detail)), /* @__PURE__ */ React.createElement("td", { className: "p-4 text-center" }, /* @__PURE__ */ React.createElement("div", { className: "text-xs text-green-300 leading-relaxed max-w-32" }, feature.threema.detail)), /* @__PURE__ */ React.createElement("td", { className: "p-4 text-center" }, /* @__PURE__ */ React.createElement("div", { className: "text-xs text-cyan-300 leading-relaxed max-w-32" }, feature.session.detail)))))) + )), /* @__PURE__ */ React.createElement("div", { className: "mt-8 grid grid-cols-2 md:grid-cols-4 gap-4 max-w-5xl mx-auto" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-center p-4 bg-yellow-500/10 border border-yellow-500/20 rounded-xl hover:bg-yellow-500/20 transition-colors" }, /* @__PURE__ */ React.createElement("span", { className: "text-yellow-400 mr-2 text-xl" }, "\u{1F3C6}"), /* @__PURE__ */ React.createElement("span", { className: "text-yellow-300 text-sm font-bold" }, "Category Leader")), /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-center p-4 bg-green-500/10 border border-green-500/20 rounded-xl hover:bg-green-500/20 transition-colors" }, /* @__PURE__ */ React.createElement("span", { className: "text-green-400 mr-2 text-xl" }, "\u2705"), /* @__PURE__ */ React.createElement("span", { className: "text-green-300 text-sm font-bold" }, "Excellent")), /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-center p-4 bg-yellow-500/10 border border-yellow-500/20 rounded-xl hover:bg-yellow-500/20 transition-colors" }, /* @__PURE__ */ React.createElement("span", { className: "text-yellow-400 mr-2 text-xl" }, "\u26A0\uFE0F"), /* @__PURE__ */ React.createElement("span", { className: "text-yellow-300 text-sm font-bold" }, "Partial/Limited")), /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-center p-4 bg-red-500/10 border border-red-500/20 rounded-xl hover:bg-red-500/20 transition-colors" }, /* @__PURE__ */ React.createElement("span", { className: "text-red-400 mr-2 text-xl" }, "\u274C"), /* @__PURE__ */ React.createElement("span", { className: "text-red-300 text-sm font-bold" }, "Not Available"))), /* @__PURE__ */ React.createElement("div", { className: "mt-10 space-y-6 max-w-6xl mx-auto" }, /* @__PURE__ */ React.createElement("div", { className: "p-6 bg-gradient-to-r from-orange-500/10 to-yellow-500/10 border border-orange-500/20 rounded-xl" }, /* @__PURE__ */ React.createElement("h4", { className: "text-xl font-bold text-orange-400 mb-4 flex items-center" }, /* @__PURE__ */ React.createElement("i", { className: "fas fa-trophy mr-3" }), "SecureBit.chat Enhanced Security Edition Summary"), /* @__PURE__ */ React.createElement("p", { className: "text-secondary leading-relaxed text-lg mb-4" }, "SecureBit.chat dominates in 11 out of 15 security categories, establishing itself as the most secure P2P messenger available. The Enhanced Security Edition introduces revolutionary 18-layer defense architecture with complete ASN.1 validation, Lightning Network integration, and military-grade cryptography that exceeds government and enterprise standards."), /* @__PURE__ */ React.createElement("div", { className: "grid md:grid-cols-2 gap-4 mt-6" }, /* @__PURE__ */ React.createElement("div", { className: "p-4 bg-orange-500/5 border border-orange-500/10 rounded-lg" }, /* @__PURE__ */ React.createElement("h5", { className: "text-orange-400 font-semibold mb-2" }, "\u{1F510} Cryptographic Superiority"), /* @__PURE__ */ React.createElement("p", { className: "text-sm text-gray-300" }, "ECDH P-384 + AES-GCM 256 + ECDSA P-384 + Complete ASN.1 Validation with non-extractable keys and 18-layer defense system")), /* @__PURE__ */ React.createElement("div", { className: "p-4 bg-orange-500/5 border border-orange-500/10 rounded-lg" }, /* @__PURE__ */ React.createElement("h5", { className: "text-orange-400 font-semibold mb-2" }, "\u26A1 Lightning Integration"), /* @__PURE__ */ React.createElement("p", { className: "text-sm text-gray-300" }, "First messenger with Lightning Network payments - sustainable economic model with instant satoshi transactions")), /* @__PURE__ */ React.createElement("div", { className: "p-4 bg-orange-500/5 border border-orange-500/10 rounded-lg" }, /* @__PURE__ */ React.createElement("h5", { className: "text-orange-400 font-semibold mb-2" }, "\u{1F310} True P2P Architecture"), /* @__PURE__ */ React.createElement("p", { className: "text-sm text-gray-300" }, "Pure WebRTC connections with zero servers, impossible to censor or shutdown, complete anonymity")), /* @__PURE__ */ React.createElement("div", { className: "p-4 bg-orange-500/5 border border-orange-500/10 rounded-lg" }, /* @__PURE__ */ React.createElement("h5", { className: "text-orange-400 font-semibold mb-2" }, "\u{1F3AD} Traffic Obfuscation"), /* @__PURE__ */ React.createElement("p", { className: "text-sm text-gray-300" }, "Advanced fake traffic generation, packet padding, and pattern masking defeat traffic analysis"))))), /* @__PURE__ */ React.createElement("div", { className: "mt-8 text-center" }, /* @__PURE__ */ React.createElement("div", { className: "inline-flex items-center px-6 py-3 bg-gray-800/50 border border-gray-600/30 rounded-xl" }, /* @__PURE__ */ React.createElement("span", { className: "text-orange-400 mr-2" }, "\u{1F680}"), /* @__PURE__ */ React.createElement("span", { className: "text-gray-300 text-sm" }, "Enhanced Security Edition v4.02.985 - ECDH + DTLS + SAS - "), /* @__PURE__ */ React.createElement("span", { className: "text-orange-400 font-semibold text-sm" }, "Active Production Release"), /* @__PURE__ */ React.createElement("span", { className: "text-gray-400 text-sm ml-2" }, " | Next: v5.0 Post-Quantum"))))); +}; +function Roadmap() { + const [selectedPhase, setSelectedPhase] = React.useState(null); + const phases = [ + { + version: "v1.0", + title: "Start of Development", + status: "done", + date: "Early 2025", + description: "Idea, prototype, and infrastructure setup", + features: [ + "Concept and requirements formation", + "Stack selection: WebRTC, P2P, cryptography", + "First messaging prototypes", + "Repository creation and CI", + "Basic encryption architecture", + "UX/UI design" + ] + }, + { + version: "v1.5", + title: "Alpha Release", + status: "done", + date: "Spring 2025", + description: "First public alpha: basic chat and key exchange", + features: [ + "Basic P2P messaging via WebRTC", + "Simple E2E encryption (demo scheme)", + "Stable signaling and reconnection", + "Minimal UX for testing", + "Feedback collection from early testers" + ] + }, + { + version: "v2.0", + title: "Security Hardened", + status: "done", + date: "Summer 2025", + description: "Security strengthening and stable branch release", + features: [ + "ECDH/ECDSA implementation in production", + "Perfect Forward Secrecy and key rotation", + "Improved authentication checks", + "File encryption and large payload transfers", + "Audit of basic cryptoprocesses" + ] + }, + { + version: "v3.0", + title: "Scaling & Stability", + status: "done", + date: "Fall 2025", + description: "Network scaling and stability improvements", + features: [ + "Optimization of P2P connections and NAT traversal", + "Reconnection mechanisms and message queues", + "Reduced battery consumption on mobile", + "Support for multi-device synchronization", + "Monitoring and logging tools for developers" + ] + }, + { + version: "v3.5", + title: "Privacy-first Release", + status: "done", + date: "Winter 2025", + description: "Focus on privacy: minimizing metadata", + features: [ + "Metadata protection and fingerprint reduction", + "Experiments with onion routing and DHT", + "Options for anonymous connections", + "Preparation for open code audit", + "Improved user verification processes" + ] + }, + // current and future phases + { + version: "v4.02.985", + title: "Enhanced Security Edition", + status: "current", + date: "Now", + description: "Current version with ECDH + DTLS + SAS security, 18-layer military-grade cryptography and complete ASN.1 validation", + features: [ + "ECDH + DTLS + SAS triple-layer security", + "ECDH P-384 + AES-GCM 256-bit encryption", + "DTLS fingerprint verification", + "SAS (Short Authentication String) verification", + "Perfect Forward Secrecy with key rotation", + "Enhanced MITM attack prevention", + "Complete ASN.1 DER validation", + "OID and EC point verification", + "SPKI structure validation", + "Lightning Network payments", + "P2P WebRTC architecture", + "Metadata protection", + "100% open source code" + ] + }, + { + version: "v4.5", + title: "Mobile & Desktop Edition", + status: "development", + date: "Q2 2025", + description: "Native apps for all platforms", + features: [ + "PWA app for mobile", + "Electron app for desktop", + "Real-time notifications", + "Automatic reconnection", + "Battery optimization", + "Cross-device synchronization", + "Improved UX/UI", + "Support for files up to 100MB" + ] + }, + { + version: "v5.0", + title: "Quantum-Resistant Edition", + status: "planned", + date: "Q4 2025", + description: "Protection against quantum computers", + features: [ + "Post-quantum cryptography CRYSTALS-Kyber", + "SPHINCS+ digital signatures", + "Hybrid scheme: classic + PQ", + "Quantum-safe key exchange", + "Updated hashing algorithms", + "Migration of existing sessions", + "Compatibility with v4.x", + "Quantum-resistant protocols" + ] + }, + { + version: "v5.5", + title: "Group Communications", + status: "planned", + date: "Q2 2026", + description: "Group chats with preserved privacy", + features: [ + "P2P group connections up to 8 participants", + "Mesh networking for groups", + "Signal Double Ratchet for groups", + "Anonymous groups without metadata", + "Ephemeral groups (disappear after session)", + "Group Lightning payments", + "Cryptographic group administration", + "Group member auditing" + ] + }, + { + version: "v6.0", + title: "Decentralized Network", + status: "research", + date: "2027", + description: "Fully decentralized network", + features: [ + "LockBit node mesh network", + "DHT for peer discovery", + "Built-in onion routing", + "Tokenomics and node incentives", + "Governance via DAO", + "Interoperability with other networks", + "Cross-platform compatibility", + "Self-healing network" + ] + }, + { + version: "v7.0", + title: "AI Privacy Assistant", + status: "research", + date: "2028+", + description: "AI for privacy and security", + features: [ + "Local AI threat analysis", + "Automatic MITM detection", + "Adaptive cryptography", + "Personalized security recommendations", + "Zero-knowledge machine learning", + "Private AI assistant", + "Predictive security", + "Autonomous attack protection" + ] + } + ]; + const getStatusConfig = (status) => { + switch (status) { + case "current": + return { + color: "green", + bgClass: "bg-green-500/10 border-green-500/20", + textClass: "text-green-400", + icon: "fas fa-check-circle", + label: "Current Version" + }; + case "development": + return { + color: "orange", + bgClass: "bg-orange-500/10 border-orange-500/20", + textClass: "text-orange-400", + icon: "fas fa-code", + label: "In Development" + }; + case "planned": + return { + color: "blue", + bgClass: "bg-blue-500/10 border-blue-500/20", + textClass: "text-blue-400", + icon: "fas fa-calendar-alt", + label: "Planned" + }; + case "research": + return { + color: "purple", + bgClass: "bg-purple-500/10 border-purple-500/20", + textClass: "text-purple-400", + icon: "fas fa-flask", + label: "Research" + }; + case "done": + return { + color: "gray", + bgClass: "bg-gray-500/10 border-gray-500/20", + textClass: "text-gray-300", + icon: "fas fa-flag-checkered", + label: "Released" + }; + default: + return { + color: "gray", + bgClass: "bg-gray-500/10 border-gray-500/20", + textClass: "text-gray-400", + icon: "fas fa-question", + label: "Unknown" + }; + } + }; + const togglePhaseDetail = (index) => { + setSelectedPhase(selectedPhase === index ? null : index); + }; + return /* @__PURE__ */ React.createElement("div", { key: "roadmap-section", className: "mt-16 px-4 sm:px-0" }, /* @__PURE__ */ React.createElement("div", { key: "section-header", className: "text-center mb-12" }, /* @__PURE__ */ React.createElement("h3", { key: "title", className: "text-2xl font-semibold text-primary mb-3" }, "Development Roadmap"), /* @__PURE__ */ React.createElement("p", { key: "subtitle", className: "text-secondary max-w-2xl mx-auto mb-6" }, "Evolution of SecureBit.chat : from initial development to quantum-resistant decentralized network with complete ASN.1 validation"), /* @__PURE__ */ React.createElement( + "div", + { + key: "roadmap-note", + className: "inline-flex items-center px-4 py-2 bg-blue-500/10 border border-blue-500/20 rounded-lg" + }, + /* @__PURE__ */ React.createElement("i", { key: "icon", className: "fas fa-rocket text-blue-400 mr-2" }), + /* @__PURE__ */ React.createElement("span", { key: "text", className: "text-blue-300 text-sm font-medium" }, "Click on a version for details") + )), /* @__PURE__ */ React.createElement("div", { key: "roadmap-container", className: "max-w-6xl mx-auto" }, /* @__PURE__ */ React.createElement("div", { key: "timeline", className: "relative" }, /* @__PURE__ */ React.createElement("div", { key: "phases", className: "space-y-8" }, phases.map((phase, index) => { + const statusConfig = getStatusConfig(phase.status); + const isExpanded = selectedPhase === index; + return /* @__PURE__ */ React.createElement("div", { key: `phase-${index}`, className: "relative" }, /* @__PURE__ */ React.createElement( + "button", + { + type: "button", + "aria-expanded": isExpanded, + onClick: () => togglePhaseDetail(index), + key: `phase-button-${index}`, + className: `card-minimal rounded-xl p-4 text-left w-full transition-all duration-300 ${isExpanded ? "ring-2 ring-" + statusConfig.color + "-500/30" : ""}` + }, + /* @__PURE__ */ React.createElement( + "div", + { + key: "phase-header", + className: "flex flex-col sm:flex-row sm:items-center sm:justify-between mb-4 space-y-2 sm:space-y-0" + }, + /* @__PURE__ */ React.createElement( + "div", + { + key: "phase-info", + className: "flex flex-col sm:flex-row sm:items-center sm:space-x-4" + }, + /* @__PURE__ */ React.createElement( + "div", + { + key: "version-badge", + className: `px-3 py-1 ${statusConfig.bgClass} border rounded-lg mb-2 sm:mb-0` + }, + /* @__PURE__ */ React.createElement( + "span", + { + key: "version", + className: `${statusConfig.textClass} font-bold text-sm` + }, + phase.version + ) + ), + /* @__PURE__ */ React.createElement("div", { key: "title-section" }, /* @__PURE__ */ React.createElement( + "h4", + { + key: "title", + className: "text-lg font-semibold text-primary" + }, + phase.title + ), /* @__PURE__ */ React.createElement( + "p", + { + key: "description", + className: "text-secondary text-sm" + }, + phase.description + )) + ), + /* @__PURE__ */ React.createElement( + "div", + { + key: "phase-meta", + className: "flex items-center space-x-3 text-sm text-gray-400 font-medium" + }, + /* @__PURE__ */ React.createElement( + "div", + { + key: "status-badge", + className: `flex items-center px-3 py-1 ${statusConfig.bgClass} border rounded-lg` + }, + /* @__PURE__ */ React.createElement( + "i", + { + key: "status-icon", + className: `${statusConfig.icon} ${statusConfig.textClass} mr-2 text-xs` + } + ), + /* @__PURE__ */ React.createElement( + "span", + { + key: "status-text", + className: `${statusConfig.textClass} text-xs font-medium` + }, + statusConfig.label + ) + ), + /* @__PURE__ */ React.createElement("div", { key: "date" }, phase.date), + /* @__PURE__ */ React.createElement( + "i", + { + key: "expand-icon", + className: `fas fa-chevron-${isExpanded ? "up" : "down"} text-gray-400 text-sm` + } + ) + ) + ), + isExpanded && /* @__PURE__ */ React.createElement( + "div", + { + key: "features-section", + className: "mt-6 pt-6 border-t border-gray-700/30" + }, + /* @__PURE__ */ React.createElement( + "h5", + { + key: "features-title", + className: "text-primary font-medium mb-4 flex items-center" + }, + /* @__PURE__ */ React.createElement( + "i", + { + key: "features-icon", + className: "fas fa-list-ul mr-2 text-sm" + } + ), + "Key features:" + ), + /* @__PURE__ */ React.createElement( + "div", + { + key: "features-grid", + className: "grid md:grid-cols-2 gap-3" + }, + phase.features.map((feature, featureIndex) => /* @__PURE__ */ React.createElement( + "div", + { + key: `feature-${featureIndex}`, + className: "flex items-center space-x-3 p-3 bg-custom-bg rounded-lg" + }, + /* @__PURE__ */ React.createElement( + "div", + { + className: `w-2 h-2 rounded-full ${statusConfig.textClass.replace( + "text-", + "bg-" + )}` + } + ), + /* @__PURE__ */ React.createElement("span", { className: "text-secondary text-sm" }, feature) + )) + ) + ) + )); + })))), /* @__PURE__ */ React.createElement("div", { key: "cta-section", className: "mt-12 text-center" }, /* @__PURE__ */ React.createElement( + "div", + { + key: "cta-card", + className: "card-minimal rounded-xl p-8 max-w-2xl mx-auto" + }, + /* @__PURE__ */ React.createElement( + "h4", + { + key: "cta-title", + className: "text-xl font-semibold text-primary mb-3" + }, + "Join the future of privacy" + ), + /* @__PURE__ */ React.createElement("p", { key: "cta-description", className: "text-secondary mb-6" }, "SecureBit.chat grows thanks to the community. Your ideas and feedback help shape the future of secure communication with complete ASN.1 validation."), + /* @__PURE__ */ React.createElement( + "div", + { + key: "cta-buttons", + className: "flex flex-col sm:flex-row gap-4 justify-center" + }, + /* @__PURE__ */ React.createElement( + "a", + { + key: "github-link", + href: "https://github.com/SecureBitChat/securebit-chat/", + className: "btn-primary text-white py-3 px-6 rounded-lg font-medium transition-all duration-200 flex items-center justify-center" + }, + /* @__PURE__ */ React.createElement("i", { key: "github-icon", className: "fab fa-github mr-2" }), + "GitHub Repository" + ), + /* @__PURE__ */ React.createElement( + "a", + { + key: "feedback-link", + href: "mailto:lockbitchat@tutanota.com", + className: "btn-secondary text-white py-3 px-6 rounded-lg font-medium transition-all duration-200 flex items-center justify-center" + }, + /* @__PURE__ */ React.createElement("i", { key: "feedback-icon", className: "fas fa-comments mr-2" }), + "Feedback" + ) + ) + ))); +} +var EnhancedCopyButton = ({ text, className = "", children }) => { + const [copied, setCopied] = React.useState(false); + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(text); + setCopied(true); + setTimeout(() => setCopied(false), 2e3); + } catch (error) { + console.error("Copy failed:", error); + const textArea = document.createElement("textarea"); + textArea.value = text; + document.body.appendChild(textArea); + textArea.select(); + document.execCommand("copy"); + document.body.removeChild(textArea); + setCopied(true); + setTimeout(() => setCopied(false), 2e3); + } + }; + return React.createElement("button", { + onClick: handleCopy, + className: `${className} transition-all duration-200` + }, [ + React.createElement("i", { + key: "icon", + className: `${copied ? "fas fa-check accent-green" : "fas fa-copy text-secondary"} mr-2` + }), + copied ? "Copied!" : children + ]); +}; +var VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, remoteConfirmed, bothConfirmed }) => { + return React.createElement("div", { + className: "card-minimal rounded-xl p-6 border-purple-500/20" + }, [ + React.createElement("div", { + key: "header", + className: "flex items-center mb-4" + }, [ + React.createElement("div", { + key: "icon", + className: "w-10 h-10 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mr-3" + }, [ + React.createElement("i", { + className: "fas fa-shield-alt accent-purple" + }) + ]), + React.createElement("h3", { + key: "title", + className: "text-lg font-medium text-primary" + }, "Security verification") + ]), + React.createElement("div", { + key: "content", + className: "space-y-4" + }, [ + React.createElement("p", { + key: "description", + className: "text-secondary text-sm" + }, "Verify the security code with your contact via another communication channel (voice, SMS, etc.):"), + React.createElement("div", { + key: "code-display", + className: "text-center" + }, [ + React.createElement("div", { + key: "code", + className: "verification-code text-2xl py-4" + }, verificationCode) + ]), + // Verification status indicators + React.createElement("div", { + key: "verification-status", + className: "space-y-2" + }, [ + React.createElement("div", { + key: "local-status", + className: `flex items-center justify-between p-2 rounded-lg ${localConfirmed ? "bg-green-500/10 border border-green-500/20" : "bg-gray-500/10 border border-gray-500/20"}` + }, [ + React.createElement("span", { + key: "local-label", + className: "text-sm text-secondary" + }, "Your confirmation:"), + React.createElement("div", { + key: "local-indicator", + className: "flex items-center" + }, [ + React.createElement("i", { + key: "local-icon", + className: `fas ${localConfirmed ? "fa-check-circle text-green-400" : "fa-clock text-gray-400"} mr-2` + }), + React.createElement("span", { + key: "local-text", + className: `text-sm ${localConfirmed ? "text-green-400" : "text-gray-400"}` + }, localConfirmed ? "Confirmed" : "Pending") + ]) + ]), + React.createElement("div", { + key: "remote-status", + className: `flex items-center justify-between p-2 rounded-lg ${remoteConfirmed ? "bg-green-500/10 border border-green-500/20" : "bg-gray-500/10 border border-gray-500/20"}` + }, [ + React.createElement("span", { + key: "remote-label", + className: "text-sm text-secondary" + }, "Peer confirmation:"), + React.createElement("div", { + key: "remote-indicator", + className: "flex items-center" + }, [ + React.createElement("i", { + key: "remote-icon", + className: `fas ${remoteConfirmed ? "fa-check-circle text-green-400" : "fa-clock text-gray-400"} mr-2` + }), + React.createElement("span", { + key: "remote-text", + className: `text-sm ${remoteConfirmed ? "text-green-400" : "text-gray-400"}` + }, remoteConfirmed ? "Confirmed" : "Pending") + ]) + ]) + ]), + React.createElement("div", { + key: "warning", + className: "p-3 bg-yellow-500/10 border border-yellow-500/20 rounded-lg" + }, [ + React.createElement("p", { + className: "text-yellow-400 text-sm flex items-center" + }, [ + React.createElement("i", { + className: "fas fa-exclamation-triangle mr-2" + }), + "Make sure the codes match exactly.!" + ]) + ]), + React.createElement("div", { + key: "buttons", + className: "flex space-x-3" + }, [ + React.createElement("button", { + key: "confirm", + onClick: onConfirm, + disabled: localConfirmed, + className: `flex-1 py-3 px-4 rounded-lg font-medium transition-all duration-200 ${localConfirmed ? "bg-gray-500/20 text-gray-400 cursor-not-allowed" : "btn-verify text-white"}` + }, [ + React.createElement("i", { + className: `fas ${localConfirmed ? "fa-check-circle" : "fa-check"} mr-2` + }), + localConfirmed ? "Confirmed" : "The codes match" + ]), + React.createElement("button", { + key: "reject", + onClick: onReject, + className: "flex-1 bg-red-500/10 hover:bg-red-500/20 text-red-400 border border-red-500/20 py-3 px-4 rounded-lg font-medium transition-all duration-200" + }, [ + React.createElement("i", { + className: "fas fa-times mr-2" + }), + "The codes do not match" + ]) + ]) + ]) + ]); +}; +var EnhancedChatMessage = ({ message, type, timestamp }) => { + const formatTime = (ts) => { + return new Date(ts).toLocaleTimeString("ru-RU", { + hour: "2-digit", + minute: "2-digit", + second: "2-digit" + }); + }; + const getMessageStyle = () => { + switch (type) { + case "sent": + return { + container: "ml-auto bg-orange-500/15 border-orange-500/20 text-primary", + icon: "fas fa-lock accent-orange", + label: "Encrypted" + }; + case "received": + return { + container: "mr-auto card-minimal text-primary", + icon: "fas fa-unlock-alt accent-green", + label: "Decrypted" + }; + case "system": + return { + container: "mx-auto bg-yellow-500/10 border border-yellow-500/20 text-yellow-400", + icon: "fas fa-info-circle accent-yellow", + label: "System" + }; + default: + return { + container: "mx-auto card-minimal text-secondary", + icon: "fas fa-circle text-muted", + label: "Unknown" + }; + } + }; + const style = getMessageStyle(); + return React.createElement("div", { + className: `message-slide mb-3 p-3 rounded-lg max-w-md break-words ${style.container} border` + }, [ + React.createElement("div", { + key: "content", + className: "flex items-start space-x-2" + }, [ + React.createElement("i", { + key: "icon", + className: `${style.icon} text-sm mt-0.5 opacity-70` + }), + React.createElement("div", { + key: "text", + className: "flex-1" + }, [ + React.createElement("div", { + key: "message", + className: "text-sm" + }, message), + timestamp && React.createElement("div", { + key: "meta", + className: "flex items-center justify-between mt-1 text-xs opacity-50" + }, [ + React.createElement("span", { + key: "time" + }, formatTime(timestamp)), + React.createElement("span", { + key: "status", + className: "text-xs" + }, style.label) + ]) + ]) + ]) + ]); +}; +var EnhancedConnectionSetup = ({ + messages, + onCreateOffer, + onCreateAnswer, + onConnect, + onClearData, + onVerifyConnection, + connectionStatus, + offerData, + answerData, + offerInput, + setOfferInput, + answerInput, + setAnswerInput, + showOfferStep, + showAnswerStep, + verificationCode, + showVerification, + offerPassword, + answerPassword, + localVerificationConfirmed, + remoteVerificationConfirmed, + bothVerificationsConfirmed +}) => { + const [mode, setMode] = React.useState("select"); + const resetToSelect = () => { + setMode("select"); + onClearData(); + }; + const handleVerificationConfirm = () => { + onVerifyConnection(true); + }; + const handleVerificationReject = () => { + onVerifyConnection(false); + }; + if (showVerification) { + return React.createElement("div", { + className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" + }, [ + React.createElement("div", { + key: "verification", + className: "w-full max-w-md" + }, [ + React.createElement(VerificationStep, { + verificationCode, + onConfirm: handleVerificationConfirm, + onReject: handleVerificationReject, + localConfirmed: localVerificationConfirmed, + remoteConfirmed: remoteVerificationConfirmed, + bothConfirmed: bothVerificationsConfirmed + }) + ]) + ]); + } + if (mode === "select") { + return React.createElement("div", { + className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" + }, [ + React.createElement("div", { + key: "selector", + className: "w-full max-w-4xl" + }, [ + React.createElement("div", { + key: "header", + className: "text-center mb-8" + }, [ + React.createElement("h2", { + key: "title", + className: "text-2xl font-semibold text-primary mb-3" + }, "Start secure communication"), + React.createElement("p", { + key: "subtitle", + className: "text-secondary max-w-2xl mx-auto" + }, "Choose a connection method for a secure channel with ECDH encryption and Perfect Forward Secrecy.") + ]), + React.createElement("div", { + key: "options", + className: "grid md:grid-cols-2 gap-6 max-w-3xl mx-auto" + }, [ + // Create Connection + React.createElement("div", { + key: "create", + onClick: () => setMode("create"), + className: "card-minimal rounded-xl p-6 cursor-pointer group" + }, [ + React.createElement("div", { + key: "icon", + className: "w-12 h-12 bg-blue-500/10 border border-blue-500/20 rounded-lg flex items-center justify-center mx-auto mb-4" + }, [ + React.createElement("i", { + className: "fas fa-plus text-xl text-blue-400" + }) + ]), + React.createElement("h3", { + key: "title", + className: "text-lg font-semibold text-primary text-center mb-3" + }, "Create channel"), + React.createElement("p", { + key: "description", + className: "text-secondary text-center text-sm mb-4" + }, "Initiate a new secure connection with encrypted exchange"), + React.createElement("div", { + key: "features", + className: "space-y-2" + }, [ + React.createElement("div", { + key: "f1", + className: "flex items-center text-sm text-muted" + }, [ + React.createElement("i", { + className: "fas fa-key accent-orange mr-2 text-xs" + }), + "Generating ECDH keys" + ]), + React.createElement("div", { + key: "f2", + className: "flex items-center text-sm text-muted" + }, [ + React.createElement("i", { + className: "fas fa-shield-alt accent-orange mr-2 text-xs" + }), + "Verification code" + ]), + React.createElement("div", { + key: "f3", + className: "flex items-center text-sm text-muted" + }, [ + React.createElement("i", { + className: "fas fa-sync-alt accent-purple mr-2 text-xs" + }), + "PFS key rotation" + ]) + ]) + ]), + // Join Connection + React.createElement("div", { + key: "join", + onClick: () => setMode("join"), + className: "card-minimal rounded-xl p-6 cursor-pointer group" + }, [ + React.createElement("div", { + key: "icon", + className: "w-12 h-12 bg-green-500/10 border border-green-500/20 rounded-lg flex items-center justify-center mx-auto mb-4" + }, [ + React.createElement("i", { + className: "fas fa-link text-xl accent-green" + }) + ]), + React.createElement("h3", { + key: "title", + className: "text-lg font-semibold text-primary text-center mb-3" + }, "Join"), + React.createElement("p", { + key: "description", + className: "text-secondary text-center text-sm mb-4" + }, "Connect to an existing secure channel"), + React.createElement("div", { + key: "features", + className: "space-y-2" + }, [ + React.createElement("div", { + key: "f1", + className: "flex items-center text-sm text-muted" + }, [ + React.createElement("i", { + className: "fas fa-paste accent-green mr-2 text-xs" + }), + "Paste Offer invitation" + ]), + React.createElement("div", { + key: "f2", + className: "flex items-center text-sm text-muted" + }, [ + React.createElement("i", { + className: "fas fa-check-circle accent-green mr-2 text-xs" + }), + "Automatic verification" + ]), + React.createElement("div", { + key: "f3", + className: "flex items-center text-sm text-muted" + }, [ + React.createElement("i", { + className: "fas fa-sync-alt accent-purple mr-2 text-xs" + }), + "PFS protection" + ]) + ]) + ]) + ]), + React.createElement("div", { + key: "security-features", + className: "grid grid-cols-2 md:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4 max-w-6xl mx-auto mt-8" + }, [ + React.createElement("div", { key: "feature1", className: "text-center p-3 sm:p-4" }, [ + React.createElement("div", { key: "icon", className: "w-10 h-10 sm:w-12 sm:h-12 bg-green-500/10 border border-green-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement("i", { className: "fas fa-key accent-green" }) + ]), + React.createElement("h4", { key: "title", className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "ECDH P-384 Key Exchange"), + React.createElement("p", { key: "desc", className: "text-xs text-muted leading-tight" }, "Military-grade elliptic curve key exchange") + ]), + React.createElement("div", { key: "feature2", className: "text-center p-3 sm:p-4" }, [ + React.createElement("div", { key: "icon", className: "w-10 h-10 sm:w-12 sm:h-12 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement("i", { className: "fas fa-user-shield accent-purple" }) + ]), + React.createElement("h4", { key: "title", className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "MITM Protection"), + React.createElement("p", { key: "desc", className: "text-xs text-muted leading-tight" }, "Out-of-band verification against attacks") + ]), + React.createElement("div", { key: "feature3", className: "text-center p-3 sm:p-4" }, [ + React.createElement("div", { key: "icon", className: "w-10 h-10 sm:w-12 sm:h-12 bg-orange-500/10 border border-orange-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement("i", { className: "fas fa-lock accent-orange" }) + ]), + React.createElement("h4", { key: "title", className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "AES-GCM 256 Encryption"), + React.createElement("p", { key: "desc", className: "text-xs text-muted leading-tight" }, "Authenticated encryption standard") + ]), + React.createElement("div", { key: "feature4", className: "text-center p-3 sm:p-4" }, [ + React.createElement("div", { key: "icon", className: "w-10 h-10 sm:w-12 sm:h-12 bg-cyan-500/10 border border-cyan-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement("i", { className: "fas fa-sync-alt accent-cyan" }) + ]), + React.createElement("h4", { key: "title", className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "Perfect Forward Secrecy"), + React.createElement("p", { key: "desc", className: "text-xs text-muted leading-tight" }, "Automatic key rotation every 5 minutes") + ]), + React.createElement("div", { key: "feature5", className: "text-center p-3 sm:p-4" }, [ + React.createElement("div", { key: "icon", className: "w-10 h-10 sm:w-12 sm:h-12 bg-blue-500/10 border border-blue-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement("i", { className: "fas fa-signature accent-blue" }) + ]), + React.createElement("h4", { key: "title", className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "ECDSA P-384 Signatures"), + React.createElement("p", { key: "desc", className: "text-xs text-muted leading-tight" }, "Digital signatures for message integrity") + ]), + React.createElement("div", { key: "feature6", className: "text-center p-3 sm:p-4" }, [ + React.createElement("div", { key: "icon", className: "w-10 h-10 sm:w-12 sm:h-12 bg-yellow-500/10 border border-yellow-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement("i", { className: "fas fa-bolt accent-yellow" }) + ]), + React.createElement("h4", { key: "title", className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "Lightning Payments"), + React.createElement("p", { key: "desc", className: "text-xs text-muted leading-tight" }, "Pay-per-session via WebLN") + ]) + ]), + // Wallet Logos Section + React.createElement("div", { + key: "wallet-logos-section", + className: "mt-8" + }, [ + React.createElement("div", { + key: "wallet-logos-header", + className: "text-center mb-4" + }, [ + React.createElement("h3", { + key: "title", + className: "text-lg font-medium text-primary mb-2" + }, "Supported Lightning wallets"), + React.createElement("p", { + key: "subtitle", + className: "text-secondary text-sm" + }, "To pay for sessions, use any of the popular wallets.") + ]), + React.createElement("div", { + key: "wallet-logos-container", + className: "wallet-logos-container" + }, [ + React.createElement("div", { + key: "wallet-logos-track", + className: "wallet-logos-track" + }, [ + // First set of logos + React.createElement("a", { + key: "alby1-link", + href: "https://getalby.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo alby" + }, [ + React.createElement("img", { + key: "alby-img1", + src: "logo/alby.svg", + alt: "Alby Lightning Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "zeus1-link", + href: "https://zeusln.app", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo zeus" + }, [ + React.createElement("img", { + key: "zeus-img1", + src: "logo/zeus.svg", + alt: "Zeus Lightning Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "wos1-link", + href: "https://www.walletofsatoshi.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo wos" + }, [ + React.createElement("img", { + key: "wos-img1", + src: "logo/wos.svg", + alt: "Wallet of Satoshi", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "muun1-link", + href: "https://muun.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo muun" + }, [ + React.createElement("img", { + key: "muun-img1", + src: "logo/muun.svg", + alt: "Muun Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "atomic1-link", + href: "https://atomicwallet.io", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo atomic" + }, [ + React.createElement("img", { + key: "atomic-img1", + src: "logo/atomic.svg", + alt: "Atomic Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "breez1-link", + href: "https://breez.technology/mobile/", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo breez" + }, [ + React.createElement("img", { + key: "breez-img1", + src: "logo/breez.svg", + alt: "Breez Lightning Wallet" + }) + ]), + React.createElement("a", { + key: "lightning-labs1-link", + href: "https://lightning.engineering", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo lightning-labs" + }, [ + React.createElement("img", { + key: "lightning-labs-img1", + src: "logo/lightning-labs.svg", + alt: "Lightning Labs" + }) + ]), + React.createElement("a", { + key: "lnbits1-link", + href: "https://lnbits.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo lnbits" + }, [ + React.createElement("img", { + key: "lnbits-img1", + src: "logo/lnbits.svg", + alt: "LNbits", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "strike1-link", + href: "https://strike.me", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo strike" + }, [ + React.createElement("img", { + key: "strike-img1", + src: "logo/strike.svg", + alt: "Strike", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "impervious1-link", + href: "https://impervious.ai", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo impervious" + }, [ + React.createElement("img", { + key: "impervious-img1", + src: "logo/impervious.svg", + alt: "Impervious", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "bitcoin-lightning1-link", + href: "https://www.blink.sv/", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo bitcoin-lightning" + }, [ + React.createElement("img", { + key: "blink-img1", + src: "logo/blink.svg", + alt: "Blink Wallet", + className: "wallet-logo-img" + }) + ]), + // Second set of logos + React.createElement("a", { + key: "alby2-link", + href: "https://getalby.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo alby" + }, [ + React.createElement("img", { + key: "alby-img2", + src: "logo/alby.svg", + alt: "Alby Lightning Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "zeus2-link", + href: "https://zeusln.app", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo zeus" + }, [ + React.createElement("img", { + key: "zeus-img2", + src: "logo/zeus.svg", + alt: "Zeus Lightning Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "wos2-link", + href: "https://www.walletofsatoshi.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo wos" + }, [ + React.createElement("img", { + key: "wos-img2", + src: "logo/wos.svg", + alt: "Wallet of Satoshi", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "muun2-link", + href: "https://muun.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo muun" + }, [ + React.createElement("img", { + key: "muun-img2", + src: "logo/muun.svg", + alt: "Muun Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "atomic2-link", + href: "https://atomicwallet.io", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo atomic" + }, [ + React.createElement("img", { + key: "atomic-img2", + src: "logo/atomic.svg", + alt: "Atomic Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "breez2-link", + href: "https://breez.technology/mobile/", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo breez" + }, [ + React.createElement("img", { + key: "breez-img2", + src: "logo/breez.svg", + alt: "Breez Lightning Wallet" + }) + ]), + React.createElement("a", { + key: "lightning-labs2-link", + href: "https://lightning.engineering", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo lightning-labs" + }, [ + React.createElement("img", { + key: "lightning-labs-img2", + src: "logo/lightning-labs.svg", + alt: "Lightning Labs" + }) + ]), + React.createElement("a", { + key: "lnbits2-link", + href: "https://lnbits.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo lnbits" + }, [ + React.createElement("img", { + key: "lnbits-img2", + src: "logo/lnbits.svg", + alt: "LNbits", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "strike2-link", + href: "https://strike.me", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo strike" + }, [ + React.createElement("img", { + key: "strike-img2", + src: "logo/strike.svg", + alt: "Strike", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "impervious2-link", + href: "https://impervious.ai", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo impervious" + }, [ + React.createElement("img", { + key: "impervious-img2", + src: "logo/impervious.svg", + alt: "Impervious", + className: "wallet-logo-img" + }) + ]), + React.createElement("a", { + key: "bitcoin-lightning2-link", + href: "https://www.blink.sv/", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo bitcoin-lightning" + }, [ + React.createElement("img", { + key: "blink-img2", + src: "logo/blink.svg", + alt: "Blink Wallet", + className: "wallet-logo-img" + }) + ]) + ]) + ]) + ]), + React.createElement(UniqueFeatureSlider, { key: "unique-features-slider" }), + React.createElement(DownloadApps, { key: "download-apps" }), + React.createElement(ComparisonTable, { key: "comparison-table" }), + React.createElement(Roadmap, { key: "roadmap" }) + ]) + ]); + } + if (mode === "create") { + return React.createElement("div", { + className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" + }, [ + React.createElement("div", { + key: "create-flow", + className: "w-full max-w-3xl space-y-6" + }, [ + React.createElement("div", { + key: "header", + className: "text-center" + }, [ + React.createElement("button", { + key: "back", + onClick: resetToSelect, + className: "mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm" + }, [ + React.createElement("i", { + className: "fas fa-arrow-left mr-2" + }), + "Back to selection" + ]), + React.createElement("h2", { + key: "title", + className: "text-xl font-semibold text-primary mb-2" + }, "Creating a secure channel") + ]), + // Step 1 + React.createElement("div", { + key: "step1", + className: "card-minimal rounded-xl p-6" + }, [ + React.createElement("div", { + key: "step-header", + className: "flex items-center mb-4" + }, [ + React.createElement("div", { + key: "number", + className: "step-number mr-3" + }, "1"), + React.createElement("h3", { + key: "title", + className: "text-lg font-medium text-primary" + }, "Generating ECDH keys and verification code") + ]), + React.createElement("p", { + key: "description", + className: "text-secondary text-sm mb-4" + }, "Creating cryptographically strong keys and codes to protect against attacks"), + React.createElement("button", { + key: "create-btn", + onClick: onCreateOffer, + disabled: connectionStatus === "connecting" || showOfferStep, + className: `w-full btn-primary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed` + }, [ + React.createElement("i", { + className: "fas fa-shield-alt mr-2" + }), + showOfferStep ? "Keys created \u2713" : "Create secure keys" + ]), + showOfferStep && React.createElement("div", { + key: "offer-result", + className: "mt-6 space-y-4" + }, [ + React.createElement("div", { + key: "success", + className: "p-3 bg-green-500/10 border border-green-500/20 rounded-lg" + }, [ + React.createElement("p", { + className: "text-green-400 text-sm font-medium flex items-center" + }, [ + React.createElement("i", { + className: "fas fa-check-circle mr-2" + }), + "Secure invitation created! Send the code to your contact:" + ]) + ]), + React.createElement("div", { + key: "offer-data", + className: "space-y-3" + }, [ + React.createElement("textarea", { + key: "textarea", + value: typeof offerData === "object" ? JSON.stringify(offerData, null, 2) : offerData, + readOnly: true, + rows: 8, + className: "w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg font-mono text-xs text-secondary resize-none custom-scrollbar" + }), + React.createElement(EnhancedCopyButton, { + key: "copy", + text: typeof offerData === "object" ? JSON.stringify(offerData, null, 2) : offerData, + className: "w-full px-3 py-2 bg-orange-500/10 hover:bg-orange-500/20 text-orange-400 border border-orange-500/20 rounded text-sm font-medium" + }, "Copy invitation code") + ]) + ]) + ]), + // Step 2 - Session Type Selection + // showOfferStep && React.createElement('div', { + // key: 'step2', + // className: "card-minimal rounded-xl p-6" + // }, [ + // React.createElement('div', { + // key: 'step-header', + // className: "flex items-center mb-4" + // }, [ + // React.createElement('div', { + // key: 'number', + // className: "w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3" + // }, '2'), + // React.createElement('h3', { + // key: 'title', + // className: "text-lg font-medium text-primary" + // }, "Select session type") + // ]), + // React.createElement('p', { + // key: 'description', + // className: "text-secondary text-sm mb-4" + // }, "Choose a session plan or use limited demo mode for testing."), + // React.createElement(SessionTypeSelector, { + // key: 'session-selector', + // onSelectType: (sessionType) => { + // // Save the selected session type + // setSelectedSessionType(sessionType); + // console.log('🎯 Session type selected:', sessionType); + // // FIX: For demo sessions, we immediately call automatic activation + // if (sessionType === 'demo') { + // console.log('🎮 Demo session selected, scheduling automatic activation...'); + // // Delay activation for 2 seconds to stabilize + // setTimeout(() => { + // if (sessionManager) { + // console.log('🚀 Triggering demo session activation from selection...'); + // handleDemoVerification(); + // } + // }, 2000); + // } + // // Open a modal payment window + // if (typeof window.showPaymentModal === 'function') { + // window.showPaymentModal(sessionType); + // } else { + // // Fallback - show session information + // console.log('Selected session type:', sessionType); + // } + // }, + // onCancel: resetToSelect, + // sessionManager: window.sessionManager + // }) + // ]), + // Step 3 - Waiting for response + showOfferStep && React.createElement("div", { + key: "step2", + className: "card-minimal rounded-xl p-6" + }, [ + React.createElement("div", { + key: "step-header", + className: "flex items-center mb-4" + }, [ + React.createElement("div", { + key: "number", + className: "w-8 h-8 bg-blue-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3" + }, "2"), + React.createElement("h3", { + key: "title", + className: "text-lg font-medium text-primary" + }, "Waiting for the peer's response") + ]), + React.createElement("p", { + key: "description", + className: "text-secondary text-sm mb-4" + }, "Paste the encrypted invitation code from your contact."), + React.createElement("textarea", { + key: "input", + value: answerInput, + onChange: (e) => setAnswerInput(e.target.value), + rows: 6, + placeholder: "Paste the encrypted response code from your contact...", + className: "w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-orange-500/40 focus:outline-none transition-all custom-scrollbar text-sm" + }), + React.createElement("button", { + key: "connect-btn", + onClick: onConnect, + disabled: !answerInput.trim(), + className: "w-full btn-secondary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" + }, [ + React.createElement("i", { + className: "fas fa-rocket mr-2" + }), + "Establish connection" + ]) + ]) + ]) + ]); + } + if (mode === "join") { + return React.createElement("div", { + className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" + }, [ + React.createElement("div", { + key: "join-flow", + className: "w-full max-w-3xl space-y-6" + }, [ + React.createElement("div", { + key: "header", + className: "text-center" + }, [ + React.createElement("button", { + key: "back", + onClick: resetToSelect, + className: "mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm" + }, [ + React.createElement("i", { + className: "fas fa-arrow-left mr-2" + }), + "Back to selection" + ]), + React.createElement("h2", { + key: "title", + className: "text-xl font-semibold text-primary mb-2" + }, "Joining the secure channel") + ]), + // Step 1 + React.createElement("div", { + key: "step1", + className: "card-minimal rounded-xl p-6" + }, [ + React.createElement("div", { + key: "step-header", + className: "flex items-center mb-4" + }, [ + React.createElement("div", { + key: "number", + className: "w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3" + }, "1"), + React.createElement("h3", { + key: "title", + className: "text-lg font-medium text-primary" + }, "Paste secure invitation") + ]), + React.createElement("p", { + key: "description", + className: "text-secondary text-sm mb-4" + }, "Copy and paste the encrypted invitation code from the initiator."), + React.createElement("textarea", { + key: "input", + value: offerInput, + onChange: (e) => setOfferInput(e.target.value), + rows: 8, + placeholder: "Paste the encrypted invitation code...", + className: "w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm" + }), + React.createElement("button", { + key: "process-btn", + onClick: onCreateAnswer, + disabled: !offerInput.trim() || connectionStatus === "connecting", + className: "w-full btn-secondary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" + }, [ + React.createElement("i", { + className: "fas fa-cogs mr-2" + }), + "Process the invitation" + ]) + ]), + // Step 2 + showAnswerStep && React.createElement("div", { + key: "step2", + className: "card-minimal rounded-xl p-6" + }, [ + React.createElement("div", { + key: "step-header", + className: "flex items-center mb-4" + }, [ + React.createElement("div", { + key: "number", + className: "step-number mr-3" + }, "2"), + React.createElement("h3", { + key: "title", + className: "text-lg font-medium text-primary" + }, "Sending a secure response") + ]), + React.createElement("div", { + key: "success", + className: "p-3 bg-green-500/10 border border-green-500/20 rounded-lg mb-4" + }, [ + React.createElement("p", { + className: "text-green-400 text-sm font-medium flex items-center" + }, [ + React.createElement("i", { + className: "fas fa-check-circle mr-2" + }), + "Secure response created! Send this code to the initiator:" + ]) + ]), + React.createElement("div", { + key: "answer-data", + className: "space-y-3 mb-4" + }, [ + React.createElement("textarea", { + key: "textarea", + value: typeof answerData === "object" ? JSON.stringify(answerData, null, 2) : answerData, + readOnly: true, + rows: 6, + className: "w-full p-3 bg-custom-bg border border-green-500/20 rounded-lg font-mono text-xs text-secondary resize-none custom-scrollbar" + }), + React.createElement(EnhancedCopyButton, { + key: "copy", + text: typeof answerData === "object" ? JSON.stringify(answerData, null, 2) : answerData, + className: "w-full px-3 py-2 bg-green-500/10 hover:bg-green-500/20 text-green-400 border border-green-500/20 rounded text-sm font-medium" + }, "Copy response code") + ]), + React.createElement("div", { + key: "info", + className: "p-3 bg-purple-500/10 border border-purple-500/20 rounded-lg" + }, [ + React.createElement("p", { + className: "text-purple-400 text-sm flex items-center justify-center" + }, [ + React.createElement("i", { + className: "fas fa-shield-alt mr-2" + }), + "The connection will be established with verification" + ]) + ]) + ]) + ]) + ]); + } +}; +var EnhancedChatInterface = ({ + messages, + messageInput, + setMessageInput, + onSendMessage, + onDisconnect, + keyFingerprint, + isVerified, + chatMessagesRef, + scrollToBottom, + webrtcManager +}) => { + const [showScrollButton, setShowScrollButton] = React.useState(false); + const [showFileTransfer, setShowFileTransfer] = React.useState(false); + React.useEffect(() => { + if (chatMessagesRef.current && messages.length > 0) { + const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current; + const isNearBottom = scrollHeight - scrollTop - clientHeight < 100; + if (isNearBottom) { + const smoothScroll = () => { + if (chatMessagesRef.current) { + chatMessagesRef.current.scrollTo({ + top: chatMessagesRef.current.scrollHeight, + behavior: "smooth" + }); + } + }; + smoothScroll(); + setTimeout(smoothScroll, 50); + setTimeout(smoothScroll, 150); + } + } + }, [messages, chatMessagesRef]); + const handleScroll = () => { + if (chatMessagesRef.current) { + const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current; + const isNearBottom = scrollHeight - scrollTop - clientHeight < 100; + setShowScrollButton(!isNearBottom); + } + }; + const handleScrollToBottom = () => { + scrollToBottom(); + setShowScrollButton(false); + }; + const handleKeyPress = (e) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + onSendMessage(); + } + }; + const isFileTransferReady = () => { + if (!webrtcManager) return false; + const connected = webrtcManager.isConnected ? webrtcManager.isConnected() : false; + const verified = webrtcManager.isVerified || false; + const hasDataChannel = webrtcManager.dataChannel && webrtcManager.dataChannel.readyState === "open"; + return connected && verified && hasDataChannel; + }; + return React.createElement( + "div", + { + className: "chat-container flex flex-col", + style: { backgroundColor: "#272827", height: "calc(100vh - 64px)" } + }, + [ + // Область сообщений + React.createElement( + "div", + { className: "flex-1 flex flex-col overflow-hidden" }, + React.createElement( + "div", + { className: "flex-1 max-w-4xl mx-auto w-full p-4 overflow-hidden" }, + React.createElement( + "div", + { + ref: chatMessagesRef, + onScroll: handleScroll, + className: "h-full overflow-y-auto space-y-3 hide-scrollbar pr-2 scroll-smooth" + }, + messages.length === 0 ? React.createElement( + "div", + { className: "flex items-center justify-center h-full" }, + React.createElement( + "div", + { className: "text-center max-w-md" }, + [ + React.createElement( + "div", + { className: "w-16 h-16 bg-green-500/10 border border-green-500/20 rounded-xl flex items-center justify-center mx-auto mb-4" }, + React.createElement( + "svg", + { className: "w-8 h-8 text-green-500", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, + React.createElement("path", { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" + }) + ) + ), + React.createElement("h3", { className: "text-lg font-medium text-gray-300 mb-2" }, "Secure channel is ready!"), + React.createElement("p", { className: "text-gray-400 text-sm mb-4" }, "All messages are protected by modern cryptographic algorithms"), + React.createElement( + "div", + { className: "text-left space-y-2" }, + [ + ["End-to-end encryption", "M5 13l4 4L19 7"], + ["Protection against replay attacks", "M5 13l4 4L19 7"], + ["Integrity verification", "M5 13l4 4L19 7"], + ["Perfect Forward Secrecy", "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"] + ].map( + ([text, d], i) => React.createElement( + "div", + { key: `f${i}`, className: "flex items-center text-sm text-gray-400" }, + [ + React.createElement( + "svg", + { + className: `w-4 h-4 mr-3 ${i === 3 ? "text-purple-500" : "text-green-500"}`, + fill: "none", + stroke: "currentColor", + viewBox: "0 0 24 24" + }, + React.createElement("path", { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d + }) + ), + text + ] + ) + ) + ) + ] + ) + ) : messages.map( + (msg) => React.createElement(EnhancedChatMessage, { + key: msg.id, + message: msg.message, + type: msg.type, + timestamp: msg.timestamp + }) + ) + ) + ) + ), + // Кнопка прокрутки вниз + showScrollButton && React.createElement( + "button", + { + onClick: handleScrollToBottom, + className: "fixed right-6 w-12 h-12 bg-green-500/20 hover:bg-green-500/30 border border-green-500/30 text-green-400 rounded-full flex items-center justify-center transition-all duration-200 shadow-lg z-50", + style: { bottom: "160px" } + }, + React.createElement( + "svg", + { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, + React.createElement("path", { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d: "M19 14l-7 7m0 0l-7-7m7 7V3" + }) + ) + ), + // Секция передачи файлов + React.createElement( + "div", + { + className: "flex-shrink-0 border-t border-gray-500/10", + style: { backgroundColor: "#272827" } + }, + React.createElement( + "div", + { className: "max-w-4xl mx-auto px-4" }, + [ + React.createElement( + "button", + { + onClick: () => setShowFileTransfer(!showFileTransfer), + className: `flex items-center text-sm text-gray-400 hover:text-gray-300 transition-colors py-4 ${showFileTransfer ? "mb-4" : ""}` + }, + [ + React.createElement( + "svg", + { + className: `w-4 h-4 mr-2 transform transition-transform ${showFileTransfer ? "rotate-180" : ""}`, + fill: "none", + stroke: "currentColor", + viewBox: "0 0 24 24" + }, + showFileTransfer ? React.createElement("path", { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d: "M5 15l7-7 7 7" + }) : React.createElement("path", { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d: "M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13" + }) + ), + showFileTransfer ? "Hide file transfer" : "Send files" + ] + ), + // ИСПРАВЛЕНИЕ: Используем правильный компонент + showFileTransfer && React.createElement(window.FileTransferComponent || (() => React.createElement("div", { + className: "p-4 text-center text-red-400" + }, "FileTransferComponent not loaded")), { + webrtcManager, + isConnected: isFileTransferReady() + }) + ] + ) + ), + // Область ввода сообщений + React.createElement( + "div", + { className: "border-t border-gray-500/10" }, + React.createElement( + "div", + { className: "max-w-4xl mx-auto p-4" }, + React.createElement( + "div", + { className: "flex items-stretch space-x-3" }, + [ + React.createElement( + "div", + { className: "flex-1 relative" }, + [ + React.createElement("textarea", { + value: messageInput, + onChange: (e) => setMessageInput(e.target.value), + onKeyDown: handleKeyPress, + placeholder: "Enter message to encrypt...", + rows: 2, + maxLength: 2e3, + style: { backgroundColor: "#272827" }, + className: "w-full p-3 border border-gray-600 rounded-lg resize-none text-gray-300 placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm" + }), + React.createElement( + "div", + { className: "absolute bottom-2 right-3 flex items-center space-x-2 text-xs text-gray-400" }, + [ + React.createElement("span", null, `${messageInput.length}/2000`), + React.createElement("span", null, "\u2022 Enter to send") + ] + ) + ] + ), + React.createElement( + "button", + { + onClick: onSendMessage, + disabled: !messageInput.trim(), + className: "bg-green-400/20 text-green-400 p-3 rounded-lg transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center min-h-[72px]" + }, + React.createElement( + "svg", + { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, + React.createElement("path", { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d: "M12 19l9 2-9-18-9 18 9-2zm0 0v-8" + }) + ) + ) + ] + ) + ) + ) + ] + ); +}; +var EnhancedSecureP2PChat = () => { + const [messages, setMessages] = React.useState([]); + const [connectionStatus, setConnectionStatus] = React.useState("disconnected"); + React.useEffect(() => { + if (messages.length > 0 && chatMessagesRef.current) { + const scrollToBottom2 = () => { + if (chatMessagesRef.current) { + chatMessagesRef.current.scrollTo({ + top: chatMessagesRef.current.scrollHeight, + behavior: "smooth" + }); + } + }; + scrollToBottom2(); + setTimeout(scrollToBottom2, 50); + setTimeout(scrollToBottom2, 150); + } + }, [messages]); + const [messageInput, setMessageInput] = React.useState(""); + const [offerData, setOfferData] = React.useState(""); + const [answerData, setAnswerData] = React.useState(""); + const [offerInput, setOfferInput] = React.useState(""); + const [answerInput, setAnswerInput] = React.useState(""); + const [keyFingerprint, setKeyFingerprint] = React.useState(""); + const [verificationCode, setVerificationCode] = React.useState(""); + const [showOfferStep, setShowOfferStep] = React.useState(false); + const [showAnswerStep, setShowAnswerStep] = React.useState(false); + const [showVerification, setShowVerification] = React.useState(false); + const [isVerified, setIsVerified] = React.useState(false); + const [securityLevel, setSecurityLevel] = React.useState(null); + const [localVerificationConfirmed, setLocalVerificationConfirmed] = React.useState(false); + const [remoteVerificationConfirmed, setRemoteVerificationConfirmed] = React.useState(false); + const [bothVerificationsConfirmed, setBothVerificationsConfirmed] = React.useState(false); + const [sessionManager, setSessionManager] = React.useState(null); + const [showPaymentModal, setShowPaymentModal] = React.useState(false); + const [sessionTimeLeft, setSessionTimeLeft] = React.useState(0); + const [pendingSession, setPendingSession] = React.useState(null); + const [selectedSessionType, setSelectedSessionType] = React.useState(null); + React.useEffect(() => { + if (window.PayPerSessionManager && !sessionManager) { + console.log("\u{1F4B0} Initializing PayPerSessionManager..."); + const newSessionManager = new window.PayPerSessionManager(); + setSessionManager(newSessionManager); + window.sessionManager = newSessionManager; + console.log("\u2705 PayPerSessionManager initialized successfully"); + } + }, [sessionManager]); + React.useEffect(() => { + if (!sessionManager) return; + window.showPaymentModal = (sessionType) => { + setShowPaymentModal(true); + if (sessionType) { + console.log("Opening payment modal for session type:", sessionType); + } + }; + window.sessionManager = sessionManager; + window.forceCleanup = () => { + handleClearData(); + if (webrtcManagerRef.current) { + webrtcManagerRef.current.disconnect(); + } + if (sessionManager) { + sessionManager.cleanup(); + } + }; + window.forceSessionReset = () => { + if (sessionManager) { + sessionManager.resetSession(); + } + setSessionTimeLeft(0); + }; + window.forceSessionCleanup = () => { + if (sessionManager) { + sessionManager.cleanup(); + } + setSessionTimeLeft(0); + setSessionManager(null); + }; + window.clearLogs = () => { + if (typeof console.clear === "function") { + console.clear(); + } + }; + return () => { + delete window.showPaymentModal; + delete window.sessionManager; + delete window.forceCleanup; + delete window.forceSessionReset; + delete window.forceSessionCleanup; + delete window.clearLogs; + }; + }, [sessionManager]); + const webrtcManagerRef = React.useRef(null); + window.webrtcManagerRef = webrtcManagerRef; + const addMessageWithAutoScroll = React.useCallback((message, type) => { + const newMessage = { + message, + type, + id: Date.now() + Math.random(), + timestamp: Date.now() + }; + setMessages((prev) => { + const updated = [...prev, newMessage]; + setTimeout(() => { + if (chatMessagesRef?.current) { + const container = chatMessagesRef.current; + try { + const { scrollTop, scrollHeight, clientHeight } = container; + const isNearBottom = scrollHeight - scrollTop - clientHeight < 100; + if (isNearBottom || prev.length === 0) { + requestAnimationFrame(() => { + if (container && container.scrollTo) { + container.scrollTo({ + top: container.scrollHeight, + behavior: "smooth" + }); + } + }); + } + } catch (error) { + console.warn("Scroll error:", error); + container.scrollTop = container.scrollHeight; + } + } + }, 50); + return updated; + }); + }, []); + const updateSecurityLevel = React.useCallback(async () => { + if (window.isUpdatingSecurity) { + return; + } + window.isUpdatingSecurity = true; + try { + if (webrtcManagerRef.current) { + const level = await webrtcManagerRef.current.calculateSecurityLevel(); + setSecurityLevel(level); + if (window.DEBUG_MODE) { + console.log("\u{1F512} Security level updated:", { + level: level.level, + score: level.score, + sessionType: level.sessionType, + passedChecks: level.passedChecks, + totalChecks: level.totalChecks + }); + } + } + } catch (error) { + console.error("Failed to update security level:", error); + setSecurityLevel({ + level: "ERROR", + score: 0, + color: "red", + details: "Verification failed" + }); + } finally { + setTimeout(() => { + window.isUpdatingSecurity = false; + }, 2e3); + } + }, []); + React.useEffect(() => { + if (!sessionManager) return; + const timer = setInterval(() => { + if (sessionManager.hasActiveSession()) { + setSessionTimeLeft(sessionManager.getTimeLeft()); + } else { + setSessionTimeLeft(0); + } + }, 1e3); + return () => clearInterval(timer); + }, [sessionManager]); + React.useEffect(() => { + if (!sessionManager) return; + sessionManager.onSessionExpired = () => { + setMessages((prev) => [...prev, { + message: "\u23F0 Session time expired. The connection will be terminated.", + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + setTimeout(() => handleDisconnect(), 3e3); + }; + }, [sessionManager]); + React.useEffect(() => { + if (!sessionManager) return; + const handleDemoVerification = async () => { + try { + if (sessionManager.hasActiveSession()) { + console.log("\u2705 Demo session already active"); + return; + } + console.log("\u{1F50D} SessionManager state before activation:", { + hasActiveSession: sessionManager.hasActiveSession(), + timeLeft: sessionManager.getTimeLeft(), + currentSession: sessionManager.currentSession + }); + window.pendingDemoActivation = true; + setTimeout(async () => { + if (window.pendingDemoActivation && sessionManager) { + let result = null; + const demoSession = sessionManager.createDemoSessionForActivation(); + if (!demoSession.success) { + return; + } + result = await sessionManager.safeActivateSession( + "demo", + demoSession.preimage, + demoSession.paymentHash + ); + if (result && result.success) { + setSessionTimeLeft(sessionManager.getTimeLeft()); + setMessages((prev) => [...prev, { + message: `\u{1F3AE} Demo session activated for ${Math.round(result.timeLeft / 6e4)} minutes`, + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + window.pendingDemoActivation = false; + } else { + window.pendingDemoActivation = false; + } + } + }, 3e3); + } catch (error) { + console.error("\u274C Error activating demo session automatically:", error); + } + }; + if (connectionStatus === "connected" && isVerified) { + setTimeout(handleDemoVerification, 1e3); + } + if (selectedSessionType === "demo" && connectionStatus === "connected" && isVerified) { + setTimeout(handleDemoVerification, 1e3); + } + }, [sessionManager, connectionStatus, isVerified, selectedSessionType]); + const chatMessagesRef = React.useRef(null); + const scrollToBottom = () => { + if (chatMessagesRef.current) { + const scrollAttempt = () => { + if (chatMessagesRef.current) { + chatMessagesRef.current.scrollTo({ + top: chatMessagesRef.current.scrollHeight, + behavior: "smooth" + }); + } + }; + scrollAttempt(); + setTimeout(scrollAttempt, 50); + setTimeout(scrollAttempt, 150); + setTimeout(scrollAttempt, 300); + requestAnimationFrame(() => { + setTimeout(scrollAttempt, 100); + }); + } + }; + React.useEffect(() => { + if (webrtcManagerRef.current) { + console.log("\u26A0\uFE0F WebRTC Manager already initialized, skipping..."); + return; + } + const handleMessage = (message, type) => { + if (typeof message === "string" && message.trim().startsWith("{")) { + try { + const parsedMessage = JSON.parse(message); + const blockedTypes = [ + "file_transfer_start", + "file_transfer_response", + "file_chunk", + "chunk_confirmation", + "file_transfer_complete", + "file_transfer_error", + "heartbeat", + "verification", + "verification_response", + "verification_confirmed", + "verification_both_confirmed", + "peer_disconnect", + "key_rotation_signal", + "key_rotation_ready", + "security_upgrade" + ]; + if (parsedMessage.type && blockedTypes.includes(parsedMessage.type)) { + console.log(`\u{1F6D1} Blocked system/file message from chat: ${parsedMessage.type}`); + return; + } + } catch (parseError) { + } + } + addMessageWithAutoScroll(message, type); + }; + const handleStatusChange = (status) => { + console.log("handleStatusChange called with status:", status); + setConnectionStatus(status); + if (status === "connected") { + document.dispatchEvent(new CustomEvent("new-connection")); + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } else if (status === "verifying") { + console.log("Setting showVerification to true for verifying status"); + setShowVerification(true); + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } else if (status === "verified") { + setIsVerified(true); + setShowVerification(false); + setBothVerificationsConfirmed(true); + setConnectionStatus("connected"); + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } else if (status === "connecting") { + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } else if (status === "disconnected") { + setConnectionStatus("disconnected"); + setIsVerified(false); + setShowVerification(false); + document.dispatchEvent(new CustomEvent("disconnected")); + setLocalVerificationConfirmed(false); + setRemoteVerificationConfirmed(false); + setBothVerificationsConfirmed(false); + setOfferData(null); + setAnswerData(null); + setOfferInput(""); + setAnswerInput(""); + setShowOfferStep(false); + setShowAnswerStep(false); + setKeyFingerprint(""); + setVerificationCode(""); + setSecurityLevel(null); + if (sessionManager && sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + setHasActiveSession(false); + } + setTimeout(() => { + setConnectionStatus("disconnected"); + setShowVerification(false); + setOfferData(null); + setAnswerData(null); + setOfferInput(""); + setAnswerInput(""); + setShowOfferStep(false); + setShowAnswerStep(false); + setMessages([]); + }, 1e3); + } else if (status === "peer_disconnected") { + if (sessionManager && sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + setHasActiveSession(false); + } + document.dispatchEvent(new CustomEvent("peer-disconnect")); + setTimeout(() => { + setKeyFingerprint(""); + setVerificationCode(""); + setSecurityLevel(null); + setIsVerified(false); + setShowVerification(false); + setConnectionStatus("disconnected"); + setLocalVerificationConfirmed(false); + setRemoteVerificationConfirmed(false); + setBothVerificationsConfirmed(false); + setOfferData(null); + setAnswerData(null); + setOfferInput(""); + setAnswerInput(""); + setShowOfferStep(false); + setShowAnswerStep(false); + setMessages([]); + setSessionManager(null); + }, 2e3); + } + }; + const handleKeyExchange = (fingerprint) => { + console.log("handleKeyExchange called with fingerprint:", fingerprint); + if (fingerprint === "") { + setKeyFingerprint(""); + } else { + setKeyFingerprint(fingerprint); + console.log("Key fingerprint set in UI:", fingerprint); + } + }; + const handleVerificationRequired = (code) => { + console.log("handleVerificationRequired called with code:", code); + if (code === "") { + setVerificationCode(""); + setShowVerification(false); + } else { + setVerificationCode(code); + setShowVerification(true); + console.log("Verification code set, showing verification UI"); + } + }; + const handleVerificationStateChange = (state) => { + console.log("handleVerificationStateChange called with state:", state); + setLocalVerificationConfirmed(state.localConfirmed); + setRemoteVerificationConfirmed(state.remoteConfirmed); + setBothVerificationsConfirmed(state.bothConfirmed); + }; + const handleAnswerError = (errorType, errorMessage) => { + if (errorType === "replay_attack") { + if (sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + } + setPendingSession(null); + addMessageWithAutoScroll("\u{1F4A1} Data is outdated. Please create a new invitation or use a current response code.", "system"); + if (typeof console.clear === "function") { + console.clear(); + } + } else if (errorType === "security_violation") { + if (sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + } + setPendingSession(null); + addMessageWithAutoScroll(`\u{1F512} Security breach: ${errorMessage}`, "system"); + if (typeof console.clear === "function") { + console.clear(); + } + } + }; + console.log("\u{1F527} Initializing WebRTC Manager..."); + if (typeof console.clear === "function") { + console.clear(); + } + webrtcManagerRef.current = new EnhancedSecureWebRTCManager( + handleMessage, + handleStatusChange, + handleKeyExchange, + handleVerificationRequired, + handleAnswerError, + handleVerificationStateChange + ); + handleMessage("\u{1F680} SecureBit.chat Enhanced Security Edition v4.02.985 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.", "system"); + const handleBeforeUnload = (event) => { + if (event.type === "beforeunload" && !isTabSwitching) { + console.log("\u{1F50C} Page unloading (closing tab) - sending disconnect notification"); + if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) { + try { + webrtcManagerRef.current.sendSystemMessage({ + type: "peer_disconnect", + reason: "user_disconnect", + timestamp: Date.now() + }); + } catch (error) { + console.log("Could not send disconnect notification:", error.message); + } + setTimeout(() => { + if (webrtcManagerRef.current) { + webrtcManagerRef.current.disconnect(); + } + }, 100); + } else if (webrtcManagerRef.current) { + webrtcManagerRef.current.disconnect(); + } + } else if (isTabSwitching) { + console.log("\u{1F4F1} Tab switching detected - NOT disconnecting"); + event.preventDefault(); + event.returnValue = ""; + } + }; + window.addEventListener("beforeunload", handleBeforeUnload); + let isTabSwitching = false; + let tabSwitchTimeout = null; + const handleVisibilityChange = () => { + if (document.visibilityState === "hidden") { + console.log("\u{1F4F1} Page hidden (tab switch) - keeping connection alive"); + isTabSwitching = true; + if (tabSwitchTimeout) { + clearTimeout(tabSwitchTimeout); + } + tabSwitchTimeout = setTimeout(() => { + isTabSwitching = false; + }, 5e3); + } else if (document.visibilityState === "visible") { + console.log("\u{1F4F1} Page visible (tab restored) - connection maintained"); + isTabSwitching = false; + if (tabSwitchTimeout) { + clearTimeout(tabSwitchTimeout); + tabSwitchTimeout = null; + } + } + }; + document.addEventListener("visibilitychange", handleVisibilityChange); + if (webrtcManagerRef.current) { + webrtcManagerRef.current.setFileTransferCallbacks( + // Progress callback + (progress) => { + console.log("File progress:", progress); + }, + // File received callback + (fileData) => { + const sizeMb = Math.max(1, Math.round((fileData.fileSize || 0) / (1024 * 1024))); + const downloadMessage = React.createElement("div", { + className: "flex items-center space-x-2" + }, [ + React.createElement("span", { key: "label" }, `\u{1F4E5} File received: ${fileData.fileName} (${sizeMb} MB)`), + React.createElement("button", { + key: "btn", + className: "px-3 py-1 rounded bg-blue-600 hover:bg-blue-700 text-white text-xs", + onClick: async () => { + try { + const url = await fileData.getObjectURL(); + const a = document.createElement("a"); + a.href = url; + a.download = fileData.fileName; + a.click(); + setTimeout(() => fileData.revokeObjectURL(url), 15e3); + } catch (e) { + console.error("Download failed:", e); + addMessageWithAutoScroll(`\u274C File upload error: ${String(e?.message || e)}`, "system"); + } + } + }, "Download") + ]); + addMessageWithAutoScroll(downloadMessage, "system"); + }, + // Error callback + (error) => { + console.error("File transfer error:", error); + if (error.includes("Connection not ready")) { + addMessageWithAutoScroll(`\u26A0\uFE0F File transfer error: connection not ready. Try again later.`, "system"); + } else if (error.includes("File too large")) { + addMessageWithAutoScroll(`\u26A0\uFE0F File is too big. Maximum size: 100 MB`, "system"); + } else { + addMessageWithAutoScroll(`\u274C File transfer error: ${error}`, "system"); + } + } + ); + } + return () => { + window.removeEventListener("beforeunload", handleBeforeUnload); + document.removeEventListener("visibilitychange", handleVisibilityChange); + if (tabSwitchTimeout) { + clearTimeout(tabSwitchTimeout); + tabSwitchTimeout = null; + } + if (webrtcManagerRef.current) { + console.log("\u{1F9F9} Cleaning up WebRTC Manager..."); + webrtcManagerRef.current.disconnect(); + webrtcManagerRef.current = null; + } + }; + }, []); + const ensureActiveSessionOrPurchase = async () => { + if (sessionManager.hasActiveSession()) return true; + if (pendingSession) return true; + setShowPaymentModal(true); + return false; + }; + const handleCreateOffer = async () => { + try { + console.log("\u{1F3AF} handleCreateOffer called"); + const ok = await ensureActiveSessionOrPurchase(); + if (!ok) return; + setOfferData(""); + setShowOfferStep(false); + console.log("\u{1F3AF} Calling createSecureOffer..."); + const offer = await webrtcManagerRef.current.createSecureOffer(); + console.log("\u{1F3AF} createSecureOffer returned:", offer ? "success" : "null"); + setOfferData(offer); + setShowOfferStep(true); + const existingMessages = messages.filter( + (m) => m.type === "system" && (m.message.includes("Secure invitation created") || m.message.includes("Send the encrypted code")) + ); + if (existingMessages.length === 0) { + setMessages((prev) => [...prev, { + message: "\u{1F510} Secure invitation created and encrypted!", + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + setMessages((prev) => [...prev, { + message: "\u{1F4E4} Send the invitation code to your interlocutor via a secure channel (voice call, SMS, etc.)..", + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + } + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } catch (error) { + setMessages((prev) => [...prev, { + message: `\u274C Error creating invitation: ${error.message}`, + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + } + }; + const handleCreateAnswer = async () => { + try { + if (!offerInput.trim()) { + setMessages((prev) => [...prev, { + message: "\u26A0\uFE0F You need to insert the invitation code from your interlocutor.", + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + return; + } + try { + setMessages((prev) => [...prev, { + message: "\u{1F504} Processing the secure invitation...", + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + setAnswerData(""); + setShowAnswerStep(false); + let offer; + try { + offer = JSON.parse(offerInput.trim()); + } catch (parseError) { + throw new Error(`Invalid invitation format: ${parseError.message}`); + } + if (!offer || typeof offer !== "object") { + throw new Error("The invitation must be an object"); + } + if (!offer.type || offer.type !== "enhanced_secure_offer") { + throw new Error("Invalid invitation type. Expected enhanced_secure_offer"); + } + console.log("Creating secure answer for offer:", offer); + const answer = await webrtcManagerRef.current.createSecureAnswer(offer); + console.log("Secure answer created:", answer); + setAnswerData(answer); + setShowAnswerStep(true); + const existingResponseMessages = messages.filter( + (m) => m.type === "system" && (m.message.includes("Secure response created") || m.message.includes("Send the response")) + ); + if (existingResponseMessages.length === 0) { + setMessages((prev) => [...prev, { + message: "\u2705 Secure response created!", + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + setMessages((prev) => [...prev, { + message: "\u{1F4E4} Send the response code to the initiator via a secure channel..", + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + } + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } catch (error) { + console.error("Error in handleCreateAnswer:", error); + setMessages((prev) => [...prev, { + message: `\u274C Error processing the invitation: ${error.message}`, + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + } + } catch (error) { + console.error("Error in handleCreateAnswer:", error); + setMessages((prev) => [...prev, { + message: `\u274C Invitation processing error: ${error.message}`, + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + } + }; + const handleConnect = async () => { + try { + if (!answerInput.trim()) { + setMessages((prev) => [...prev, { + message: "\u26A0\uFE0F You need to insert the response code from your interlocutor.", + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + return; + } + try { + setMessages((prev) => [...prev, { + message: "\u{1F504} Processing the secure response...", + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + let answer; + try { + answer = JSON.parse(answerInput.trim()); + } catch (parseError) { + throw new Error(`Invalid response format: ${parseError.message}`); + } + if (!answer || typeof answer !== "object") { + throw new Error("The response must be an object"); + } + if (!answer.type || answer.type !== "enhanced_secure_answer") { + throw new Error("Invalid response type. Expected enhanced_secure_answer"); + } + await webrtcManagerRef.current.handleSecureAnswer(answer); + if (sessionManager.canActivateSession() && pendingSession) { + const result = sessionManager.safeActivateSession(pendingSession.type, pendingSession.preimage, pendingSession.paymentHash); + if (result.success) { + setPendingSession(null); + setSessionTimeLeft(sessionManager.getTimeLeft()); + setMessages((prev) => [...prev, { + message: `\u{1F4B0} Session activated on ${sessionManager.sessionPrices[pendingSession.type].hours}\u0447 (${result.method})`, + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + } else { + setMessages((prev) => [...prev, { + message: `\u274C Session activation error: ${result.reason}`, + type: "error", + id: Date.now(), + timestamp: Date.now() + }]); + } + } + setMessages((prev) => [...prev, { + message: "\u{1F504} Finalizing the secure connection...", + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } catch (error) { + setMessages((prev) => [...prev, { + message: `\u274C Connection setup error: ${error.message}`, + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + if (!error.message.includes("Too old") && !error.message.includes("too old")) { + setPendingSession(null); + } + } + } catch (error) { + setMessages((prev) => [...prev, { + message: `\u274C Connection setup error: ${error.message}`, + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + if (!error.message.includes("\u0441Too old") && !error.message.includes("too old")) { + setPendingSession(null); + } + } + }; + const handleVerifyConnection = (isValid) => { + if (isValid) { + webrtcManagerRef.current.confirmVerification(); + setLocalVerificationConfirmed(true); + } else { + setMessages((prev) => [...prev, { + message: "\u274C Verification rejected. The connection is unsafe! Session reset..", + type: "system", + id: Date.now(), + timestamp: Date.now() + }]); + setLocalVerificationConfirmed(false); + setRemoteVerificationConfirmed(false); + setBothVerificationsConfirmed(false); + setShowVerification(false); + setVerificationCode(""); + setConnectionStatus("disconnected"); + setOfferData(null); + setAnswerData(null); + setOfferInput(""); + setAnswerInput(""); + setShowOfferStep(false); + setShowAnswerStep(false); + setKeyFingerprint(""); + setSecurityLevel(null); + setIsVerified(false); + setMessages([]); + sessionManager.resetSession(); + setSessionTimeLeft(0); + setPendingSession(null); + document.dispatchEvent(new CustomEvent("disconnected")); + handleDisconnect(); + } + }; + const handleSendMessage = async () => { + if (!messageInput.trim()) { + return; + } + if (!webrtcManagerRef.current) { + return; + } + if (!webrtcManagerRef.current.isConnected()) { + return; + } + try { + addMessageWithAutoScroll(messageInput.trim(), "sent"); + await webrtcManagerRef.current.sendMessage(messageInput); + setMessageInput(""); + } catch (error) { + const msg = String(error?.message || error); + if (!/queued for sending|Data channel not ready/i.test(msg)) { + addMessageWithAutoScroll(`\u274C Sending error: ${msg}`, "system"); + } + } + }; + const handleClearData = () => { + setOfferData(""); + setAnswerData(""); + setOfferInput(""); + setAnswerInput(""); + setShowOfferStep(false); + setShowAnswerStep(false); + setShowVerification(false); + setVerificationCode(""); + setIsVerified(false); + setKeyFingerprint(""); + setSecurityLevel(null); + setConnectionStatus("disconnected"); + setMessages([]); + setMessageInput(""); + setLocalVerificationConfirmed(false); + setRemoteVerificationConfirmed(false); + setBothVerificationsConfirmed(false); + if (sessionManager) { + sessionManager.cleanup(); + setSessionTimeLeft(0); + } + setShowPaymentModal(false); + setPendingSession(null); + document.dispatchEvent(new CustomEvent("peer-disconnect")); + setSessionManager(null); + }; + const handleDisconnect = () => { + if (sessionManager && sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + } + if (sessionManager) { + sessionManager.cleanup(); + } + setShowPaymentModal(false); + if (webrtcManagerRef.current) { + webrtcManagerRef.current.disconnect(); + } + setKeyFingerprint(""); + setVerificationCode(""); + setSecurityLevel(null); + setIsVerified(false); + setShowVerification(false); + setConnectionStatus("disconnected"); + setLocalVerificationConfirmed(false); + setRemoteVerificationConfirmed(false); + setBothVerificationsConfirmed(false); + setConnectionStatus("disconnected"); + setShowVerification(false); + setOfferData(null); + setAnswerData(null); + setOfferInput(""); + setAnswerInput(""); + setShowOfferStep(false); + setShowAnswerStep(false); + setKeyFingerprint(""); + setVerificationCode(""); + setSecurityLevel(null); + setIsVerified(false); + setMessages([]); + document.dispatchEvent(new CustomEvent("peer-disconnect")); + document.dispatchEvent(new CustomEvent("disconnected")); + document.dispatchEvent(new CustomEvent("session-cleanup", { + detail: { + timestamp: Date.now(), + reason: "manual_disconnect" + } + })); + setTimeout(() => { + if (sessionManager && sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + } + }, 500); + handleClearData(); + setTimeout(() => { + setSessionManager(null); + }, 1e3); + }; + const handleSessionActivated = (session) => { + let message; + if (session.type === "demo") { + message = `\u{1F3AE} Demo session activated for 6 minutes. You can create invitations!`; + } else { + const hours = sessionManager.sessionPrices[session.type]?.hours || 0; + message = `\u{1F4B0} Session activated for ${hours}h. You can create invitations!`; + } + addMessageWithAutoScroll(message, "system"); + }; + React.useEffect(() => { + if (connectionStatus === "connected" && isVerified) { + addMessageWithAutoScroll("\u{1F389} Secure connection successfully established and verified! You can now communicate safely with full protection against MITM attacks and Perfect Forward Secrecy..", "system"); + } + }, [connectionStatus, isVerified]); + const isConnectedAndVerified = connectionStatus === "connected" && isVerified; + React.useEffect(() => { + if (isConnectedAndVerified && sessionManager.canActivateSession() && pendingSession && connectionStatus !== "failed") { + const result = sessionManager.safeActivateSession(pendingSession.type, pendingSession.preimage, pendingSession.paymentHash); + if (result.success) { + setPendingSession(null); + setSessionTimeLeft(sessionManager.getTimeLeft()); + let message; + if (pendingSession.type === "demo") { + message = `\u{1F3AE} Demo session activated for 6 minutes (${result.method})`; + } else { + const hours = sessionManager.sessionPrices[pendingSession.type]?.hours || 0; + message = `\u{1F4B0} Session activated for ${hours}h (${result.method})`; + } + addMessageWithAutoScroll(message, "system"); + } else { + addMessageWithAutoScroll(`\u274C Session activation error: ${result.reason}`, "error"); + } + } + }, [isConnectedAndVerified, sessionManager, pendingSession, connectionStatus]); + return React.createElement("div", { + className: "minimal-bg min-h-screen" + }, [ + React.createElement(EnhancedMinimalHeader, { + key: "header", + status: connectionStatus, + fingerprint: keyFingerprint, + verificationCode, + onDisconnect: handleDisconnect, + isConnected: isConnectedAndVerified, + securityLevel, + sessionManager, + sessionTimeLeft + }), + React.createElement( + "main", + { + key: "main" + }, + isConnectedAndVerified ? React.createElement(EnhancedChatInterface, { + messages, + messageInput, + setMessageInput, + onSendMessage: handleSendMessage, + onDisconnect: handleDisconnect, + keyFingerprint, + isVerified, + chatMessagesRef, + webrtcManager: webrtcManagerRef.current + }) : React.createElement(EnhancedConnectionSetup, { + onCreateOffer: handleCreateOffer, + onCreateAnswer: handleCreateAnswer, + onConnect: handleConnect, + onClearData: handleClearData, + onVerifyConnection: handleVerifyConnection, + connectionStatus, + offerData, + answerData, + offerInput, + setOfferInput, + answerInput, + setAnswerInput, + showOfferStep, + showAnswerStep, + verificationCode, + showVerification, + messages, + localVerificationConfirmed, + remoteVerificationConfirmed, + bothVerificationsConfirmed + // PAKE passwords removed - using SAS verification instead + }) + ), + // PAKE Password Modal removed - using SAS verification instead + // Payment Modal + React.createElement(PaymentModal, { + key: "payment-modal", + isOpen: showPaymentModal, + onClose: () => setShowPaymentModal(false), + sessionManager, + onSessionPurchased: (session) => { + setPendingSession(session); + handleSessionActivated({ type: session.type }); + } + }) + ]); +}; +function initializeApp() { + if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureWebRTCManager) { + ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById("root")); + } else { + console.error("\u274C \u041C\u043E\u0434\u0443\u043B\u0438 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u044B:", { + hasCrypto: !!window.EnhancedSecureCryptoUtils, + hasWebRTC: !!window.EnhancedSecureWebRTCManager + }); + } +} +if (typeof window !== "undefined" && !window.initializeApp) { + window.initializeApp = initializeApp; +} +ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById("root")); +//# sourceMappingURL=app.js.map diff --git a/dist/app.js.map b/dist/app.js.map new file mode 100644 index 0000000..c38ca31 --- /dev/null +++ b/dist/app.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../src/app.jsx"], + "sourcesContent": [" \r\n // Slider Component\r\n const UniqueFeatureSlider = () => {\r\n const [currentSlide, setCurrentSlide] = React.useState(0);\r\n \r\n const slides = [\r\n {\r\n icon: \"fas fa-shield-halved\",\r\n color: \"orange\",\r\n title: \"18-Layer Military Security\",\r\n description: \"Revolutionary defense system with ECDH P-384 + AES-GCM 256 + ECDSA + Complete ASN.1 Validation. Enhanced Security Edition provides military-grade protection exceeding government standards with complete key structure verification.\"\r\n },\r\n {\r\n icon: \"fas fa-bolt\",\r\n color: \"yellow\",\r\n title: \"Lightning Network Payments\",\r\n description: \"First messenger with Lightning Network integration. Pay-per-session with satoshis via WebLN. Sustainable economic model without ads or data harvesting.\"\r\n },\r\n {\r\n icon: \"fas fa-network-wired\",\r\n color: \"purple\",\r\n title: \"Pure P2P WebRTC Architecture\",\r\n description: \"Direct peer-to-peer connections without any servers. Impossible to censor, block, or monitor. Complete decentralization with zero infrastructure.\"\r\n },\r\n {\r\n icon: \"fas fa-sync-alt\",\r\n color: \"green\",\r\n title: \"Perfect Forward Secrecy\",\r\n description: \"Automatic key rotation every 5 minutes or 100 messages. Non-extractable keys with hardware protection ensure past messages remain secure.\"\r\n },\r\n {\r\n icon: \"fas fa-user-secret\",\r\n color: \"cyan\",\r\n title: \"Advanced Traffic Obfuscation\",\r\n description: \"Fake traffic generation, packet padding, and pattern masking make communication indistinguishable from random noise. Defeats traffic analysis.\"\r\n },\r\n {\r\n icon: \"fas fa-eye-slash\",\r\n color: \"blue\",\r\n title: \"Zero Data Collection\",\r\n description: \"No registration, no servers, no logs. Messages exist only in browser memory. Complete anonymity with instant anonymous channels.\"\r\n },\r\n {\r\n icon: \"fas fa-code\",\r\n color: \"emerald\",\r\n title: \"100% Open Source Security\",\r\n description: \"All code is open for audit under MIT license. Uses only standard WebCrypto APIs. Cryptography runs directly in browser without server dependencies.\"\r\n }\r\n ];\r\n \r\n const nextSlide = () => setCurrentSlide((prev) => (prev + 1) % slides.length);\r\n const prevSlide = () => setCurrentSlide((prev) => (prev - 1 + slides.length) % slides.length);\r\n const goToSlide = (index) => setCurrentSlide(index);\r\n \r\n React.useEffect(() => {\r\n const timer = setInterval(() => {\r\n nextSlide();\r\n }, 15000);\r\n return () => clearInterval(timer);\r\n }, []);\r\n \r\n return React.createElement('div', {\r\n className: \"mt-12\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"text-center mb-8\"\r\n }, [\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-2xl font-semibold text-primary mb-3\"\r\n }, 'Why SecureBit.chat is unique'),\r\n React.createElement('p', {\r\n key: 'subtitle',\r\n className: \"text-secondary max-w-2xl mx-auto\"\r\n }, 'The only messenger with military-grade cryptography and Lightning payments')\r\n ]),\r\n \r\n React.createElement('div', {\r\n key: 'slider-container',\r\n className: \"relative max-w-4xl mx-auto\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'slider-wrapper',\r\n className: \"overflow-hidden rounded-xl\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'slides',\r\n className: \"flex transition-transform duration-500 ease-in-out\",\r\n style: { transform: `translateX(-${currentSlide * 100}%)` }\r\n }, slides.map((slide, index) =>\r\n React.createElement('div', {\r\n key: index,\r\n className: \"w-full flex-shrink-0 px-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'slide-content',\r\n className: \"card-minimal rounded-xl p-8 text-center min-h-[300px] flex flex-col justify-center relative overflow-hidden\"\r\n }, [\r\n // Background icon\r\n React.createElement('i', {\r\n key: 'bg-icon',\r\n className: `${slide.icon} absolute right-[-100px] top-1/2 -translate-y-1/2 opacity-10 text-[300px] pointer-events-none ${\r\n slide.color === 'orange' ? 'text-orange-500' :\r\n slide.color === 'yellow' ? 'text-yellow-500' :\r\n slide.color === 'purple' ? 'text-purple-500' :\r\n slide.color === 'green' ? 'text-green-500' :\r\n slide.color === 'cyan' ? 'text-cyan-500' :\r\n slide.color === 'blue' ? 'text-blue-500' :\r\n 'text-emerald-500'\r\n }`\r\n }),\r\n \r\n // Content\r\n React.createElement('h4', {\r\n key: 'slide-title',\r\n className: \"text-xl font-semibold text-primary mb-4 relative z-10\"\r\n }, slide.title),\r\n React.createElement('p', {\r\n key: 'slide-description',\r\n className: \"text-secondary leading-relaxed max-w-2xl mx-auto relative z-10\"\r\n }, slide.description)\r\n ])\r\n ])\r\n ))\r\n ]),\r\n \r\n // Navigation\r\n React.createElement('button', {\r\n key: 'prev-btn',\r\n onClick: prevSlide,\r\n className: \"absolute left-2 top-1/2 transform -translate-y-1/2 w-10 h-10 bg-gray-600/80 hover:bg-gray-500/80 text-white rounded-full flex items-center justify-center transition-all duration-200 z-10\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'prev-icon',\r\n className: \"fas fa-chevron-left\"\r\n })\r\n ]),\r\n React.createElement('button', {\r\n key: 'next-btn',\r\n onClick: nextSlide,\r\n className: \"absolute right-2 top-1/2 transform -translate-y-1/2 w-10 h-10 bg-gray-600/80 hover:bg-gray-500/80 text-white rounded-full flex items-center justify-center transition-all duration-200 z-10\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'next-icon',\r\n className: \"fas fa-chevron-right\"\r\n })\r\n ])\r\n ]),\r\n \r\n // Enhanced dots navigation (\u043E\u0441\u0442\u0430\u0432\u043B\u044F\u0435\u043C \u0443\u043B\u0443\u0447\u0448\u0435\u043D\u043D\u044B\u0435 \u0442\u043E\u0447\u043A\u0438)\r\n React.createElement('div', {\r\n key: 'dots-container',\r\n className: \"flex justify-center space-x-3 mt-6\"\r\n }, slides.map((slide, index) =>\r\n React.createElement('button', {\r\n key: index,\r\n onClick: () => goToSlide(index),\r\n className: `relative group transition-all duration-300 ${\r\n index === currentSlide\r\n ? 'w-12 h-4 bg-orange-500 rounded-full'\r\n : 'w-4 h-4 bg-gray-600 hover:bg-gray-500 rounded-full hover:scale-125'\r\n }`\r\n }, [\r\n // Tooltip on hover\r\n React.createElement('div', {\r\n key: 'tooltip',\r\n className: \"absolute -top-10 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white text-xs px-2 py-1 rounded opacity-0 group-hover:opacity-100 transition-opacity duration-200 whitespace-nowrap pointer-events-none\"\r\n }, slide.title)\r\n ])\r\n ))\r\n ]);\r\n };\r\n \r\n \r\n \r\n const ComparisonTable = () => {\r\n const [selectedFeature, setSelectedFeature] = React.useState(null);\r\n \r\n const messengers = [\r\n {\r\n name: \"SecureBit.chat\",\r\n logo:
\r\n \r\n
,\r\n type: \"P2P WebRTC\",\r\n version: \"Latest\",\r\n color: \"orange\",\r\n },\r\n {\r\n name: \"Signal\",\r\n logo: (\r\n \r\n \r\n \r\n \r\n ),\r\n type: \"Centralized\",\r\n version: \"Latest\",\r\n color: \"blue\",\r\n },\r\n {\r\n name: \"Threema\",\r\n logo: (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n ),\r\n type: \"Centralized\",\r\n version: \"Latest\",\r\n color: \"green\",\r\n },\r\n {\r\n name: \"Session\",\r\n logo: (\r\n \r\n \r\n \r\n \r\n ),\r\n type: \"Onion Network\",\r\n version: \"Latest\",\r\n color: \"cyan\",\r\n },\r\n ];\r\n \r\n const features = [\r\n {\r\n name: \"Security Architecture\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"18-layer military-grade defense system with complete ASN.1 validation\" },\r\n signal: { status: \"\u2705\", detail: \"Signal Protocol with double ratchet\" },\r\n threema: { status: \"\u2705\", detail: \"Standard security implementation\" },\r\n session: { status: \"\u2705\", detail: \"Modified Signal Protocol + Onion routing\" },\r\n },\r\n {\r\n name: \"Cryptography\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"ECDH P-384 + AES-GCM 256 + ECDSA P-384\" },\r\n signal: { status: \"\u2705\", detail: \"Signal Protocol + Double Ratchet\" },\r\n threema: { status: \"\u2705\", detail: \"NaCl + XSalsa20 + Poly1305\" },\r\n session: { status: \"\u2705\", detail: \"Modified Signal Protocol\" },\r\n },\r\n {\r\n name: \"Perfect Forward Secrecy\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"Auto rotation every 5 minutes or 100 messages\" },\r\n signal: { status: \"\u2705\", detail: \"Double Ratchet algorithm\" },\r\n threema: { status: \"\u26A0\uFE0F\", detail: \"Partial (group chats)\" },\r\n session: { status: \"\u2705\", detail: \"Session Ratchet algorithm\" },\r\n },\r\n {\r\n name: \"Architecture\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"Pure P2P WebRTC without servers\" },\r\n signal: { status: \"\u274C\", detail: \"Centralized Signal servers\" },\r\n threema: { status: \"\u274C\", detail: \"Threema servers in Switzerland\" },\r\n session: { status: \"\u26A0\uFE0F\", detail: \"Onion routing via network nodes\" },\r\n },\r\n {\r\n name: \"Registration Anonymity\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"No registration required, instant anonymous channels\" },\r\n signal: { status: \"\u274C\", detail: \"Phone number required\" },\r\n threema: { status: \"\u2705\", detail: \"ID generated locally\" },\r\n session: { status: \"\u2705\", detail: \"Random session ID\" },\r\n },\r\n {\r\n name: \"Payment Integration\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"Lightning Network satoshis per session + WebLN\" },\r\n signal: { status: \"\u274C\", detail: \"No payment system\" },\r\n threema: { status: \"\u274C\", detail: \"No payment system\" },\r\n session: { status: \"\u274C\", detail: \"No payment system\" },\r\n },\r\n {\r\n name: \"Metadata Protection\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"Full metadata encryption + traffic obfuscation\" },\r\n signal: { status: \"\u26A0\uFE0F\", detail: \"Sealed Sender (partial)\" },\r\n threema: { status: \"\u26A0\uFE0F\", detail: \"Minimal metadata\" },\r\n session: { status: \"\u2705\", detail: \"Onion routing hides metadata\" },\r\n },\r\n {\r\n name: \"Traffic Obfuscation\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"Fake traffic + pattern masking + packet padding\" },\r\n signal: { status: \"\u274C\", detail: \"No traffic obfuscation\" },\r\n threema: { status: \"\u274C\", detail: \"No traffic obfuscation\" },\r\n session: { status: \"\u2705\", detail: \"Onion routing provides obfuscation\" },\r\n },\r\n {\r\n name: \"Open Source\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"100% open + auditable + MIT license\" },\r\n signal: { status: \"\u2705\", detail: \"Fully open\" },\r\n threema: { status: \"\u26A0\uFE0F\", detail: \"Only clients open\" },\r\n session: { status: \"\u2705\", detail: \"Fully open\" },\r\n },\r\n {\r\n name: \"MITM Protection\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"Out-of-band verification + mutual auth + ECDSA\" },\r\n signal: { status: \"\u2705\", detail: \"Safety numbers verification\" },\r\n threema: { status: \"\u2705\", detail: \"QR code scanning\" },\r\n session: { status: \"\u26A0\uFE0F\", detail: \"Basic key verification\" },\r\n },\r\n {\r\n name: \"Economic Model\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"Sustainable pay-per-session model\" },\r\n signal: { status: \"\u26A0\uFE0F\", detail: \"Donations and grants dependency\" },\r\n threema: { status: \"\u2705\", detail: \"One-time app purchase\" },\r\n session: { status: \"\u26A0\uFE0F\", detail: \"Donations dependency\" },\r\n },\r\n {\r\n name: \"Censorship Resistance\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"Impossible to block P2P + no servers to target\" },\r\n signal: { status: \"\u26A0\uFE0F\", detail: \"Blocked in authoritarian countries\" },\r\n threema: { status: \"\u26A0\uFE0F\", detail: \"May be blocked\" },\r\n session: { status: \"\u2705\", detail: \"Onion routing bypasses blocks\" },\r\n },\r\n {\r\n name: \"Data Storage\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"Zero data storage - only in browser memory\" },\r\n signal: { status: \"\u26A0\uFE0F\", detail: \"Local database storage\" },\r\n threema: { status: \"\u26A0\uFE0F\", detail: \"Local + optional backup\" },\r\n session: { status: \"\u26A0\uFE0F\", detail: \"Local database storage\" },\r\n },\r\n {\r\n name: \"Key Security\",\r\n lockbit: { status: \"\uD83C\uDFC6\", detail: \"Non-extractable keys + hardware protection\" },\r\n signal: { status: \"\u2705\", detail: \"Secure key storage\" },\r\n threema: { status: \"\u2705\", detail: \"Local key storage\" },\r\n session: { status: \"\u2705\", detail: \"Secure key storage\" },\r\n },\r\n {\r\n name: \"Post-Quantum Roadmap\",\r\n lockbit: { status: \"\u2705\", detail: \"Planned v5.0 - CRYSTALS-Kyber/Dilithium\" },\r\n signal: { status: \"\u26A0\uFE0F\", detail: \"PQXDH in development\" },\r\n threema: { status: \"\u274C\", detail: \"Not announced\" },\r\n session: { status: \"\u274C\", detail: \"Not announced\" },\r\n },\r\n ];\r\n \r\n const getStatusIcon = (status) => {\r\n const statusMap = {\r\n \"\uD83C\uDFC6\": { icon: \"\uD83C\uDFC6\", color: \"text-yellow-400\" },\r\n \"\u2705\": { icon: \"\u2705\", color: \"text-green-400\" },\r\n \"\u26A0\uFE0F\": { icon: \"\u26A0\uFE0F\", color: \"text-yellow-400\" },\r\n \"\u274C\": { icon: \"\u274C\", color: \"text-red-400\" },\r\n };\r\n return statusMap[status] || { icon: status, color: \"text-gray-400\" };\r\n };\r\n \r\n const toggleFeatureDetail = (index) => {\r\n setSelectedFeature(selectedFeature === index ? null : index);\r\n };\r\n \r\n return (\r\n
\r\n {/* Title */}\r\n
\r\n

\r\n Enhanced Security Edition Comparison\r\n

\r\n

\r\n Enhanced Security Edition vs leading secure messengers\r\n

\r\n
\r\n \uD83C\uDFC6\r\n \r\n Category Leader - Military-Grade Security\r\n \r\n
\r\n
\r\n \r\n {/* Table container */}\r\n
\r\n {/* Mobile Alert */}\r\n
\r\n

\r\n \uD83D\uDCA1 Rotate your device horizontally for better viewing\r\n

\r\n
\r\n \r\n {/* Table */}\r\n
\r\n \r\n {/* Table Header */}\r\n \r\n \r\n \r\n Security Criterion\r\n \r\n {messengers.map((messenger, index) => (\r\n \r\n
\r\n
{messenger.logo}
\r\n
\r\n {messenger.name}\r\n
\r\n
{messenger.type}
\r\n
{messenger.version}
\r\n
\r\n \r\n ))}\r\n \r\n \r\n \r\n {/* Table body*/}\r\n \r\n {features.map((feature, featureIndex) => (\r\n \r\n toggleFeatureDetail(featureIndex)}\r\n >\r\n \r\n
\r\n {feature.name}\r\n \r\n
\r\n \r\n \r\n \r\n {getStatusIcon(feature.lockbit.status).icon}\r\n \r\n \r\n \r\n \r\n {getStatusIcon(feature.signal.status).icon}\r\n \r\n \r\n \r\n \r\n {getStatusIcon(feature.threema.status).icon}\r\n \r\n \r\n \r\n \r\n {getStatusIcon(feature.session.status).icon}\r\n \r\n \r\n \r\n \r\n {/* Details */}\r\n {selectedFeature === featureIndex && (\r\n \r\n Technical Details:\r\n \r\n
\r\n {feature.lockbit.detail}\r\n
\r\n \r\n \r\n
\r\n {feature.signal.detail}\r\n
\r\n \r\n \r\n
\r\n {feature.threema.detail}\r\n
\r\n \r\n \r\n
\r\n {feature.session.detail}\r\n
\r\n \r\n \r\n )}\r\n
\r\n ))}\r\n \r\n \r\n
\r\n \r\n {/* Legend */}\r\n
\r\n
\r\n \uD83C\uDFC6\r\n Category Leader\r\n
\r\n
\r\n \u2705\r\n Excellent\r\n
\r\n
\r\n \u26A0\uFE0F\r\n Partial/Limited\r\n
\r\n
\r\n \u274C\r\n Not Available\r\n
\r\n
\r\n \r\n {/* Legend */}\r\n
\r\n
\r\n

\r\n \r\n SecureBit.chat Enhanced Security Edition Summary\r\n

\r\n

\r\n SecureBit.chat dominates in 11 out of 15 security categories, establishing itself as the most secure P2P messenger available.\r\n The Enhanced Security Edition introduces revolutionary 18-layer defense architecture with complete ASN.1 validation, Lightning Network integration, and military-grade cryptography that exceeds government and enterprise standards.\r\n

\r\n
\r\n
\r\n
\uD83D\uDD10 Cryptographic Superiority
\r\n

\r\n ECDH P-384 + AES-GCM 256 + ECDSA P-384 + Complete ASN.1 Validation with non-extractable keys and 18-layer defense system\r\n

\r\n
\r\n
\r\n
\u26A1 Lightning Integration
\r\n

\r\n First messenger with Lightning Network payments - sustainable economic model with instant satoshi transactions\r\n

\r\n
\r\n
\r\n
\uD83C\uDF10 True P2P Architecture
\r\n

\r\n Pure WebRTC connections with zero servers, impossible to censor or shutdown, complete anonymity\r\n

\r\n
\r\n
\r\n
\uD83C\uDFAD Traffic Obfuscation
\r\n

\r\n Advanced fake traffic generation, packet padding, and pattern masking defeat traffic analysis\r\n

\r\n
\r\n
\r\n
\r\n
\r\n \r\n {/* Version information */}\r\n
\r\n
\r\n \uD83D\uDE80\r\n Enhanced Security Edition v4.02.985 - ECDH + DTLS + SAS - \r\n Active Production Release\r\n | Next: v5.0 Post-Quantum\r\n
\r\n
\r\n
\r\n
\r\n );\r\n };\r\n \r\n function Roadmap() {\r\n const [selectedPhase, setSelectedPhase] = React.useState(null);\r\n const phases = [\r\n {\r\n version: \"v1.0\",\r\n title: \"Start of Development\",\r\n status: \"done\",\r\n date: \"Early 2025\",\r\n description: \"Idea, prototype, and infrastructure setup\",\r\n features: [\r\n \"Concept and requirements formation\",\r\n \"Stack selection: WebRTC, P2P, cryptography\",\r\n \"First messaging prototypes\",\r\n \"Repository creation and CI\",\r\n \"Basic encryption architecture\",\r\n \"UX/UI design\"\r\n ]\r\n },\r\n {\r\n version: \"v1.5\",\r\n title: \"Alpha Release\",\r\n status: \"done\",\r\n date: \"Spring 2025\",\r\n description: \"First public alpha: basic chat and key exchange\",\r\n features: [\r\n \"Basic P2P messaging via WebRTC\",\r\n \"Simple E2E encryption (demo scheme)\",\r\n \"Stable signaling and reconnection\",\r\n \"Minimal UX for testing\",\r\n \"Feedback collection from early testers\"\r\n ]\r\n },\r\n {\r\n version: \"v2.0\",\r\n title: \"Security Hardened\",\r\n status: \"done\",\r\n date: \"Summer 2025\",\r\n description: \"Security strengthening and stable branch release\",\r\n features: [\r\n \"ECDH/ECDSA implementation in production\",\r\n \"Perfect Forward Secrecy and key rotation\",\r\n \"Improved authentication checks\",\r\n \"File encryption and large payload transfers\",\r\n \"Audit of basic cryptoprocesses\"\r\n ]\r\n },\r\n {\r\n version: \"v3.0\",\r\n title: \"Scaling & Stability\",\r\n status: \"done\",\r\n date: \"Fall 2025\",\r\n description: \"Network scaling and stability improvements\",\r\n features: [\r\n \"Optimization of P2P connections and NAT traversal\",\r\n \"Reconnection mechanisms and message queues\",\r\n \"Reduced battery consumption on mobile\",\r\n \"Support for multi-device synchronization\",\r\n \"Monitoring and logging tools for developers\"\r\n ]\r\n },\r\n {\r\n version: \"v3.5\",\r\n title: \"Privacy-first Release\",\r\n status: \"done\",\r\n date: \"Winter 2025\",\r\n description: \"Focus on privacy: minimizing metadata\",\r\n features: [\r\n \"Metadata protection and fingerprint reduction\",\r\n \"Experiments with onion routing and DHT\",\r\n \"Options for anonymous connections\",\r\n \"Preparation for open code audit\",\r\n \"Improved user verification processes\"\r\n ]\r\n },\r\n \r\n // current and future phases\r\n {\r\n version: \"v4.02.985\",\r\n title: \"Enhanced Security Edition\",\r\n status: \"current\",\r\n date: \"Now\",\r\n description: \"Current version with ECDH + DTLS + SAS security, 18-layer military-grade cryptography and complete ASN.1 validation\",\r\n features: [\r\n \"ECDH + DTLS + SAS triple-layer security\",\r\n \"ECDH P-384 + AES-GCM 256-bit encryption\",\r\n \"DTLS fingerprint verification\",\r\n \"SAS (Short Authentication String) verification\",\r\n \"Perfect Forward Secrecy with key rotation\",\r\n \"Enhanced MITM attack prevention\",\r\n \"Complete ASN.1 DER validation\",\r\n \"OID and EC point verification\",\r\n \"SPKI structure validation\",\r\n \"Lightning Network payments\",\r\n \"P2P WebRTC architecture\",\r\n \"Metadata protection\",\r\n \"100% open source code\"\r\n ]\r\n },\r\n {\r\n version: \"v4.5\",\r\n title: \"Mobile & Desktop Edition\",\r\n status: \"development\",\r\n date: \"Q2 2025\",\r\n description: \"Native apps for all platforms\",\r\n features: [\r\n \"PWA app for mobile\",\r\n \"Electron app for desktop\",\r\n \"Real-time notifications\",\r\n \"Automatic reconnection\",\r\n \"Battery optimization\",\r\n \"Cross-device synchronization\",\r\n \"Improved UX/UI\",\r\n \"Support for files up to 100MB\"\r\n ]\r\n },\r\n {\r\n version: \"v5.0\",\r\n title: \"Quantum-Resistant Edition\",\r\n status: \"planned\",\r\n date: \"Q4 2025\",\r\n description: \"Protection against quantum computers\",\r\n features: [\r\n \"Post-quantum cryptography CRYSTALS-Kyber\",\r\n \"SPHINCS+ digital signatures\",\r\n \"Hybrid scheme: classic + PQ\",\r\n \"Quantum-safe key exchange\",\r\n \"Updated hashing algorithms\",\r\n \"Migration of existing sessions\",\r\n \"Compatibility with v4.x\",\r\n \"Quantum-resistant protocols\"\r\n ]\r\n },\r\n {\r\n version: \"v5.5\",\r\n title: \"Group Communications\",\r\n status: \"planned\",\r\n date: \"Q2 2026\",\r\n description: \"Group chats with preserved privacy\",\r\n features: [\r\n \"P2P group connections up to 8 participants\",\r\n \"Mesh networking for groups\",\r\n \"Signal Double Ratchet for groups\",\r\n \"Anonymous groups without metadata\",\r\n \"Ephemeral groups (disappear after session)\",\r\n \"Group Lightning payments\",\r\n \"Cryptographic group administration\",\r\n \"Group member auditing\"\r\n ]\r\n },\r\n {\r\n version: \"v6.0\",\r\n title: \"Decentralized Network\",\r\n status: \"research\",\r\n date: \"2027\",\r\n description: \"Fully decentralized network\",\r\n features: [\r\n \"LockBit node mesh network\",\r\n \"DHT for peer discovery\",\r\n \"Built-in onion routing\",\r\n \"Tokenomics and node incentives\",\r\n \"Governance via DAO\",\r\n \"Interoperability with other networks\",\r\n \"Cross-platform compatibility\",\r\n \"Self-healing network\"\r\n ]\r\n },\r\n {\r\n version: \"v7.0\",\r\n title: \"AI Privacy Assistant\",\r\n status: \"research\",\r\n date: \"2028+\",\r\n description: \"AI for privacy and security\",\r\n features: [\r\n \"Local AI threat analysis\",\r\n \"Automatic MITM detection\",\r\n \"Adaptive cryptography\",\r\n \"Personalized security recommendations\",\r\n \"Zero-knowledge machine learning\",\r\n \"Private AI assistant\",\r\n \"Predictive security\",\r\n \"Autonomous attack protection\"\r\n ]\r\n }\r\n ];\r\n \r\n \r\n const getStatusConfig = (status) => {\r\n switch (status) {\r\n case 'current':\r\n return {\r\n color: 'green',\r\n bgClass: 'bg-green-500/10 border-green-500/20',\r\n textClass: 'text-green-400',\r\n icon: 'fas fa-check-circle',\r\n label: 'Current Version'\r\n };\r\n case 'development':\r\n return {\r\n color: 'orange',\r\n bgClass: 'bg-orange-500/10 border-orange-500/20',\r\n textClass: 'text-orange-400',\r\n icon: 'fas fa-code',\r\n label: 'In Development'\r\n };\r\n case 'planned':\r\n return {\r\n color: 'blue',\r\n bgClass: 'bg-blue-500/10 border-blue-500/20',\r\n textClass: 'text-blue-400',\r\n icon: 'fas fa-calendar-alt',\r\n label: 'Planned'\r\n };\r\n case 'research':\r\n return {\r\n color: 'purple',\r\n bgClass: 'bg-purple-500/10 border-purple-500/20',\r\n textClass: 'text-purple-400',\r\n icon: 'fas fa-flask',\r\n label: 'Research'\r\n };\r\n case 'done':\r\n return {\r\n color: 'gray',\r\n bgClass: 'bg-gray-500/10 border-gray-500/20',\r\n textClass: 'text-gray-300',\r\n icon: 'fas fa-flag-checkered',\r\n label: 'Released'\r\n };\r\n default:\r\n return {\r\n color: 'gray',\r\n bgClass: 'bg-gray-500/10 border-gray-500/20',\r\n textClass: 'text-gray-400',\r\n icon: 'fas fa-question',\r\n label: 'Unknown'\r\n };\r\n }\r\n };\r\n \r\n \r\n const togglePhaseDetail = (index) => {\r\n setSelectedPhase(selectedPhase === index ? null : index);\r\n };\r\n return (\r\n
\r\n
\r\n

\r\n Development Roadmap\r\n

\r\n

\r\n Evolution of SecureBit.chat : from initial development to quantum-resistant decentralized network with complete ASN.1 validation\r\n

\r\n \r\n \r\n \r\n Click on a version for details\r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n {/* The line has been removed */}\r\n \r\n
\r\n {phases.map((phase, index) => {\r\n const statusConfig = getStatusConfig(phase.status);\r\n const isExpanded = selectedPhase === index;\r\n \r\n return (\r\n
\r\n {/* The dots are visible only on sm and larger screens */}\r\n \r\n togglePhaseDetail(index)}\r\n key={`phase-button-${index}`}\r\n className={`card-minimal rounded-xl p-4 text-left w-full transition-all duration-300 ${\r\n isExpanded\r\n ? \"ring-2 ring-\" + statusConfig.color + \"-500/30\"\r\n : \"\"\r\n }`}\r\n >\r\n \r\n \r\n \r\n \r\n {phase.version}\r\n \r\n
\r\n \r\n
\r\n \r\n {phase.title}\r\n \r\n \r\n {phase.description}\r\n

\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n {statusConfig.label}\r\n \r\n
\r\n \r\n
{phase.date}
\r\n \r\n
\r\n \r\n \r\n {isExpanded && (\r\n \r\n \r\n \r\n Key features:\r\n \r\n \r\n \r\n {phase.features.map((feature, featureIndex) => (\r\n \r\n \r\n \r\n {feature}\r\n \r\n \r\n ))}\r\n \r\n \r\n )}\r\n \r\n \r\n );\r\n })}\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n Join the future of privacy\r\n \r\n

\r\n SecureBit.chat grows thanks to the community. Your ideas and feedback help shape the future of secure communication with complete ASN.1 validation.\r\n

\r\n \r\n \r\n \r\n \r\n GitHub Repository\r\n \r\n \r\n \r\n \r\n Feedback\r\n \r\n
\r\n \r\n \r\n \r\n );\r\n }\r\n \r\n \r\n // Enhanced Copy Button with better UX\r\n const EnhancedCopyButton = ({ text, className = \"\", children }) => {\r\n const [copied, setCopied] = React.useState(false);\r\n \r\n const handleCopy = async () => {\r\n try {\r\n await navigator.clipboard.writeText(text);\r\n setCopied(true);\r\n setTimeout(() => setCopied(false), 2000);\r\n } catch (error) {\r\n console.error('Copy failed:', error);\r\n // Fallback for older browsers\r\n const textArea = document.createElement('textarea');\r\n textArea.value = text;\r\n document.body.appendChild(textArea);\r\n textArea.select();\r\n document.execCommand('copy');\r\n document.body.removeChild(textArea);\r\n setCopied(true);\r\n setTimeout(() => setCopied(false), 2000);\r\n }\r\n };\r\n \r\n return React.createElement('button', {\r\n onClick: handleCopy,\r\n className: `${className} transition-all duration-200`\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: `${copied ? 'fas fa-check accent-green' : 'fas fa-copy text-secondary'} mr-2`\r\n }),\r\n copied ? 'Copied!' : children\r\n ]);\r\n };\r\n \r\n // Verification Component\r\n const VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, remoteConfirmed, bothConfirmed }) => {\r\n return React.createElement('div', {\r\n className: \"card-minimal rounded-xl p-6 border-purple-500/20\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'icon',\r\n className: \"w-10 h-10 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mr-3\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt accent-purple'\r\n })\r\n ]),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Security verification\")\r\n ]),\r\n React.createElement('div', {\r\n key: 'content',\r\n className: \"space-y-4\"\r\n }, [\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm\"\r\n }, \"Verify the security code with your contact via another communication channel (voice, SMS, etc.):\"),\r\n React.createElement('div', {\r\n key: 'code-display',\r\n className: \"text-center\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'code',\r\n className: \"verification-code text-2xl py-4\"\r\n }, verificationCode)\r\n ]),\r\n // Verification status indicators\r\n React.createElement('div', {\r\n key: 'verification-status',\r\n className: \"space-y-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'local-status',\r\n className: `flex items-center justify-between p-2 rounded-lg ${localConfirmed ? 'bg-green-500/10 border border-green-500/20' : 'bg-gray-500/10 border border-gray-500/20'}`\r\n }, [\r\n React.createElement('span', {\r\n key: 'local-label',\r\n className: \"text-sm text-secondary\"\r\n }, \"Your confirmation:\"),\r\n React.createElement('div', {\r\n key: 'local-indicator',\r\n className: \"flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'local-icon',\r\n className: `fas ${localConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2`\r\n }),\r\n React.createElement('span', {\r\n key: 'local-text',\r\n className: `text-sm ${localConfirmed ? 'text-green-400' : 'text-gray-400'}`\r\n }, localConfirmed ? 'Confirmed' : 'Pending')\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'remote-status',\r\n className: `flex items-center justify-between p-2 rounded-lg ${remoteConfirmed ? 'bg-green-500/10 border border-green-500/20' : 'bg-gray-500/10 border border-gray-500/20'}`\r\n }, [\r\n React.createElement('span', {\r\n key: 'remote-label',\r\n className: \"text-sm text-secondary\"\r\n }, \"Peer confirmation:\"),\r\n React.createElement('div', {\r\n key: 'remote-indicator',\r\n className: \"flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'remote-icon',\r\n className: `fas ${remoteConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2`\r\n }),\r\n React.createElement('span', {\r\n key: 'remote-text',\r\n className: `text-sm ${remoteConfirmed ? 'text-green-400' : 'text-gray-400'}`\r\n }, remoteConfirmed ? 'Confirmed' : 'Pending')\r\n ])\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'warning',\r\n className: \"p-3 bg-yellow-500/10 border border-yellow-500/20 rounded-lg\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-yellow-400 text-sm flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-exclamation-triangle mr-2'\r\n }),\r\n 'Make sure the codes match exactly.!'\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'buttons',\r\n className: \"flex space-x-3\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'confirm',\r\n onClick: onConfirm,\r\n disabled: localConfirmed,\r\n className: `flex-1 py-3 px-4 rounded-lg font-medium transition-all duration-200 ${localConfirmed ? 'bg-gray-500/20 text-gray-400 cursor-not-allowed' : 'btn-verify text-white'}`\r\n }, [\r\n React.createElement('i', {\r\n className: `fas ${localConfirmed ? 'fa-check-circle' : 'fa-check'} mr-2`\r\n }),\r\n localConfirmed ? 'Confirmed' : 'The codes match'\r\n ]),\r\n React.createElement('button', {\r\n key: 'reject',\r\n onClick: onReject,\r\n className: \"flex-1 bg-red-500/10 hover:bg-red-500/20 text-red-400 border border-red-500/20 py-3 px-4 rounded-lg font-medium transition-all duration-200\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-times mr-2'\r\n }),\r\n 'The codes do not match'\r\n ])\r\n ])\r\n ])\r\n ]);\r\n };\r\n \r\n // Enhanced Chat Message with better security indicators\r\n const EnhancedChatMessage = ({ message, type, timestamp }) => {\r\n const formatTime = (ts) => {\r\n return new Date(ts).toLocaleTimeString('ru-RU', { \r\n hour: '2-digit', \r\n minute: '2-digit',\r\n second: '2-digit'\r\n });\r\n };\r\n \r\n const getMessageStyle = () => {\r\n switch (type) {\r\n case 'sent':\r\n return {\r\n container: \"ml-auto bg-orange-500/15 border-orange-500/20 text-primary\",\r\n icon: \"fas fa-lock accent-orange\",\r\n label: \"Encrypted\"\r\n };\r\n case 'received':\r\n return {\r\n container: \"mr-auto card-minimal text-primary\",\r\n icon: \"fas fa-unlock-alt accent-green\",\r\n label: \"Decrypted\"\r\n };\r\n case 'system':\r\n return {\r\n container: \"mx-auto bg-yellow-500/10 border border-yellow-500/20 text-yellow-400\",\r\n icon: \"fas fa-info-circle accent-yellow\",\r\n label: \"System\"\r\n };\r\n default:\r\n return {\r\n container: \"mx-auto card-minimal text-secondary\",\r\n icon: \"fas fa-circle text-muted\",\r\n label: \"Unknown\"\r\n };\r\n }\r\n };\r\n \r\n const style = getMessageStyle();\r\n \r\n return React.createElement('div', {\r\n className: `message-slide mb-3 p-3 rounded-lg max-w-md break-words ${style.container} border`\r\n }, [\r\n React.createElement('div', {\r\n key: 'content',\r\n className: \"flex items-start space-x-2\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: `${style.icon} text-sm mt-0.5 opacity-70`\r\n }),\r\n React.createElement('div', {\r\n key: 'text',\r\n className: \"flex-1\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'message',\r\n className: \"text-sm\"\r\n }, message),\r\n timestamp && React.createElement('div', {\r\n key: 'meta',\r\n className: \"flex items-center justify-between mt-1 text-xs opacity-50\"\r\n }, [\r\n React.createElement('span', {\r\n key: 'time'\r\n }, formatTime(timestamp)),\r\n React.createElement('span', {\r\n key: 'status',\r\n className: \"text-xs\"\r\n }, style.label)\r\n ])\r\n ])\r\n ])\r\n ]);\r\n };\r\n \r\n // Enhanced Connection Setup with verification\r\n const EnhancedConnectionSetup = ({\r\n messages, \r\n onCreateOffer, \r\n onCreateAnswer, \r\n onConnect, \r\n onClearData,\r\n onVerifyConnection,\r\n connectionStatus,\r\n offerData,\r\n answerData,\r\n offerInput,\r\n setOfferInput,\r\n answerInput,\r\n setAnswerInput,\r\n showOfferStep,\r\n showAnswerStep,\r\n verificationCode,\r\n showVerification,\r\n offerPassword,\r\n answerPassword,\r\n localVerificationConfirmed,\r\n remoteVerificationConfirmed,\r\n bothVerificationsConfirmed\r\n }) => {\r\n const [mode, setMode] = React.useState('select');\r\n \r\n const resetToSelect = () => {\r\n setMode('select');\r\n onClearData();\r\n };\r\n \r\n const handleVerificationConfirm = () => {\r\n onVerifyConnection(true);\r\n };\r\n \r\n const handleVerificationReject = () => {\r\n onVerifyConnection(false);\r\n };\r\n \r\n if (showVerification) {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'verification',\r\n className: \"w-full max-w-md\"\r\n }, [\r\n React.createElement(VerificationStep, {\r\n verificationCode: verificationCode,\r\n onConfirm: handleVerificationConfirm,\r\n onReject: handleVerificationReject,\r\n localConfirmed: localVerificationConfirmed,\r\n remoteConfirmed: remoteVerificationConfirmed,\r\n bothConfirmed: bothVerificationsConfirmed\r\n })\r\n ])\r\n ]);\r\n }\r\n \r\n if (mode === 'select') {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'selector',\r\n className: \"w-full max-w-4xl\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"text-center mb-8\"\r\n }, [\r\n React.createElement('h2', {\r\n key: 'title',\r\n className: \"text-2xl font-semibold text-primary mb-3\"\r\n }, 'Start secure communication'),\r\n React.createElement('p', {\r\n key: 'subtitle',\r\n className: \"text-secondary max-w-2xl mx-auto\"\r\n }, \"Choose a connection method for a secure channel with ECDH encryption and Perfect Forward Secrecy.\")\r\n ]),\r\n \r\n React.createElement('div', {\r\n key: 'options',\r\n className: \"grid md:grid-cols-2 gap-6 max-w-3xl mx-auto\"\r\n }, [\r\n // Create Connection\r\n React.createElement('div', {\r\n key: 'create',\r\n onClick: () => setMode('create'),\r\n className: \"card-minimal rounded-xl p-6 cursor-pointer group\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'icon',\r\n className: \"w-12 h-12 bg-blue-500/10 border border-blue-500/20 rounded-lg flex items-center justify-center mx-auto mb-4\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-plus text-xl text-blue-400'\r\n })\r\n ]),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-semibold text-primary text-center mb-3\"\r\n }, \"Create channel\"),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-center text-sm mb-4\"\r\n }, \"Initiate a new secure connection with encrypted exchange\"),\r\n React.createElement('div', {\r\n key: 'features',\r\n className: \"space-y-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'f1',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-key accent-orange mr-2 text-xs'\r\n }),\r\n 'Generating ECDH keys'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f2',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt accent-orange mr-2 text-xs'\r\n }),\r\n 'Verification code'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f3',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-sync-alt accent-purple mr-2 text-xs'\r\n }),\r\n 'PFS key rotation'\r\n ])\r\n ])\r\n ]),\r\n \r\n // Join Connection\r\n React.createElement('div', {\r\n key: 'join',\r\n onClick: () => setMode('join'),\r\n className: \"card-minimal rounded-xl p-6 cursor-pointer group\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'icon',\r\n className: \"w-12 h-12 bg-green-500/10 border border-green-500/20 rounded-lg flex items-center justify-center mx-auto mb-4\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-link text-xl accent-green'\r\n })\r\n ]),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-semibold text-primary text-center mb-3\"\r\n }, \"Join\"),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-center text-sm mb-4\"\r\n }, \"Connect to an existing secure channel\"),\r\n React.createElement('div', {\r\n key: 'features',\r\n className: \"space-y-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'f1',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-paste accent-green mr-2 text-xs'\r\n }),\r\n 'Paste Offer invitation'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f2',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-check-circle accent-green mr-2 text-xs'\r\n }),\r\n 'Automatic verification'\r\n ]),\r\n React.createElement('div', {\r\n key: 'f3',\r\n className: \"flex items-center text-sm text-muted\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-sync-alt accent-purple mr-2 text-xs'\r\n }),\r\n 'PFS protection'\r\n ])\r\n ])\r\n ])\r\n ]),\r\n \r\n \r\n React.createElement('div', {\r\n key: 'security-features',\r\n className: \"grid grid-cols-2 md:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4 max-w-6xl mx-auto mt-8\"\r\n }, [\r\n React.createElement('div', { key: 'feature1', className: \"text-center p-3 sm:p-4\" }, [\r\n React.createElement('div', { key: 'icon', className: \"w-10 h-10 sm:w-12 sm:h-12 bg-green-500/10 border border-green-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3\" }, [\r\n React.createElement('i', { className: 'fas fa-key accent-green' })\r\n ]),\r\n React.createElement('h4', { key: 'title', className: \"text-xs sm:text-sm font-medium text-primary mb-1\" }, \"ECDH P-384 Key Exchange\"),\r\n React.createElement('p', { key: 'desc', className: \"text-xs text-muted leading-tight\" }, \"Military-grade elliptic curve key exchange\")\r\n ]),\r\n React.createElement('div', { key: 'feature2', className: \"text-center p-3 sm:p-4\" }, [\r\n React.createElement('div', { key: 'icon', className: \"w-10 h-10 sm:w-12 sm:h-12 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3\" }, [\r\n React.createElement('i', { className: 'fas fa-user-shield accent-purple' })\r\n ]),\r\n React.createElement('h4', { key: 'title', className: \"text-xs sm:text-sm font-medium text-primary mb-1\" }, \"MITM Protection\"),\r\n React.createElement('p', { key: 'desc', className: \"text-xs text-muted leading-tight\" }, \"Out-of-band verification against attacks\")\r\n ]),\r\n React.createElement('div', { key: 'feature3', className: \"text-center p-3 sm:p-4\" }, [\r\n React.createElement('div', { key: 'icon', className: \"w-10 h-10 sm:w-12 sm:h-12 bg-orange-500/10 border border-orange-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3\" }, [\r\n React.createElement('i', { className: 'fas fa-lock accent-orange' })\r\n ]),\r\n React.createElement('h4', { key: 'title', className: \"text-xs sm:text-sm font-medium text-primary mb-1\" }, \"AES-GCM 256 Encryption\"),\r\n React.createElement('p', { key: 'desc', className: \"text-xs text-muted leading-tight\" }, \"Authenticated encryption standard\")\r\n ]),\r\n React.createElement('div', { key: 'feature4', className: \"text-center p-3 sm:p-4\" }, [\r\n React.createElement('div', { key: 'icon', className: \"w-10 h-10 sm:w-12 sm:h-12 bg-cyan-500/10 border border-cyan-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3\" }, [\r\n React.createElement('i', { className: 'fas fa-sync-alt accent-cyan' })\r\n ]),\r\n React.createElement('h4', { key: 'title', className: \"text-xs sm:text-sm font-medium text-primary mb-1\" }, \"Perfect Forward Secrecy\"),\r\n React.createElement('p', { key: 'desc', className: \"text-xs text-muted leading-tight\" }, \"Automatic key rotation every 5 minutes\")\r\n ]),\r\n React.createElement('div', { key: 'feature5', className: \"text-center p-3 sm:p-4\" }, [\r\n React.createElement('div', { key: 'icon', className: \"w-10 h-10 sm:w-12 sm:h-12 bg-blue-500/10 border border-blue-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3\" }, [\r\n React.createElement('i', { className: 'fas fa-signature accent-blue' })\r\n ]),\r\n React.createElement('h4', { key: 'title', className: \"text-xs sm:text-sm font-medium text-primary mb-1\" }, \"ECDSA P-384 Signatures\"),\r\n React.createElement('p', { key: 'desc', className: \"text-xs text-muted leading-tight\" }, \"Digital signatures for message integrity\")\r\n ]),\r\n React.createElement('div', { key: 'feature6', className: \"text-center p-3 sm:p-4\" }, [\r\n React.createElement('div', { key: 'icon', className: \"w-10 h-10 sm:w-12 sm:h-12 bg-yellow-500/10 border border-yellow-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3\" }, [\r\n React.createElement('i', { className: 'fas fa-bolt accent-yellow' })\r\n ]),\r\n React.createElement('h4', { key: 'title', className: \"text-xs sm:text-sm font-medium text-primary mb-1\" }, \"Lightning Payments\"),\r\n React.createElement('p', { key: 'desc', className: \"text-xs text-muted leading-tight\" }, \"Pay-per-session via WebLN\")\r\n ])\r\n ]),\r\n \r\n // Wallet Logos Section\r\n React.createElement('div', {\r\n key: 'wallet-logos-section',\r\n className: \"mt-8\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'wallet-logos-header',\r\n className: \"text-center mb-4\"\r\n }, [\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary mb-2\"\r\n }, \"Supported Lightning wallets\"),\r\n React.createElement('p', {\r\n key: 'subtitle',\r\n className: \"text-secondary text-sm\"\r\n }, \"To pay for sessions, use any of the popular wallets.\")\r\n ]),\r\n React.createElement('div', {\r\n key: 'wallet-logos-container',\r\n className: \"wallet-logos-container\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'wallet-logos-track',\r\n className: \"wallet-logos-track\"\r\n }, [\r\n // First set of logos\r\n React.createElement('a', { \r\n key: 'alby1-link', \r\n href: \"https://getalby.com\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo alby\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'alby-img1',\r\n src: \"logo/alby.svg\",\r\n alt: \"Alby Lightning Wallet\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'zeus1-link', \r\n href: \"https://zeusln.app\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo zeus\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'zeus-img1',\r\n src: \"logo/zeus.svg\",\r\n alt: \"Zeus Lightning Wallet\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'wos1-link', \r\n href: \"https://www.walletofsatoshi.com\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo wos\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'wos-img1',\r\n src: \"logo/wos.svg\",\r\n alt: \"Wallet of Satoshi\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'muun1-link', \r\n href: \"https://muun.com\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo muun\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'muun-img1',\r\n src: \"logo/muun.svg\",\r\n alt: \"Muun Wallet\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'atomic1-link', \r\n href: \"https://atomicwallet.io\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo atomic\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'atomic-img1',\r\n src: \"logo/atomic.svg\",\r\n alt: \"Atomic Wallet\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'breez1-link', \r\n href: \"https://breez.technology/mobile/\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo breez\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'breez-img1',\r\n src: \"logo/breez.svg\",\r\n alt: \"Breez Lightning Wallet\",\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'lightning-labs1-link', \r\n href: \"https://lightning.engineering\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo lightning-labs\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'lightning-labs-img1',\r\n src: \"logo/lightning-labs.svg\",\r\n alt: \"Lightning Labs\",\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'lnbits1-link', \r\n href: \"https://lnbits.com\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo lnbits\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'lnbits-img1',\r\n src: \"logo/lnbits.svg\",\r\n alt: \"LNbits\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'strike1-link', \r\n href: \"https://strike.me\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo strike\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'strike-img1',\r\n src: \"logo/strike.svg\",\r\n alt: \"Strike\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'impervious1-link', \r\n href: \"https://impervious.ai\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo impervious\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'impervious-img1',\r\n src: \"logo/impervious.svg\",\r\n alt: \"Impervious\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'bitcoin-lightning1-link', \r\n href: \"https://www.blink.sv/\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo bitcoin-lightning\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'blink-img1',\r\n src: \"logo/blink.svg\",\r\n alt: \"Blink Wallet\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n // Second set of logos\r\n React.createElement('a', { \r\n key: 'alby2-link', \r\n href: \"https://getalby.com\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo alby\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'alby-img2',\r\n src: \"logo/alby.svg\",\r\n alt: \"Alby Lightning Wallet\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'zeus2-link', \r\n href: \"https://zeusln.app\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo zeus\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'zeus-img2',\r\n src: \"logo/zeus.svg\",\r\n alt: \"Zeus Lightning Wallet\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'wos2-link', \r\n href: \"https://www.walletofsatoshi.com\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo wos\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'wos-img2',\r\n src: \"logo/wos.svg\",\r\n alt: \"Wallet of Satoshi\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'muun2-link', \r\n href: \"https://muun.com\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo muun\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'muun-img2',\r\n src: \"logo/muun.svg\",\r\n alt: \"Muun Wallet\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'atomic2-link', \r\n href: \"https://atomicwallet.io\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo atomic\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'atomic-img2',\r\n src: \"logo/atomic.svg\",\r\n alt: \"Atomic Wallet\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'breez2-link', \r\n href: \"https://breez.technology/mobile/\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo breez\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'breez-img2',\r\n src: \"logo/breez.svg\",\r\n alt: \"Breez Lightning Wallet\",\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'lightning-labs2-link', \r\n href: \"https://lightning.engineering\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo lightning-labs\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'lightning-labs-img2',\r\n src: \"logo/lightning-labs.svg\",\r\n alt: \"Lightning Labs\",\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'lnbits2-link', \r\n href: \"https://lnbits.com\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo lnbits\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'lnbits-img2',\r\n src: \"logo/lnbits.svg\",\r\n alt: \"LNbits\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'strike2-link', \r\n href: \"https://strike.me\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo strike\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'strike-img2',\r\n src: \"logo/strike.svg\",\r\n alt: \"Strike\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'impervious2-link', \r\n href: \"https://impervious.ai\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo impervious\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'impervious-img2',\r\n src: \"logo/impervious.svg\",\r\n alt: \"Impervious\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ]),\r\n React.createElement('a', { \r\n key: 'bitcoin-lightning2-link', \r\n href: \"https://www.blink.sv/\", \r\n target: \"_blank\", \r\n rel: \"noindex nofollow\",\r\n className: \"wallet-logo bitcoin-lightning\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'blink-img2',\r\n src: \"logo/blink.svg\",\r\n alt: \"Blink Wallet\",\r\n className: \"wallet-logo-img\"\r\n })\r\n ])\r\n ])\r\n ])\r\n ]),\r\n React.createElement(UniqueFeatureSlider, { key: 'unique-features-slider' }),\r\n \r\n React.createElement(DownloadApps, { key: 'download-apps' }),\r\n \r\n React.createElement(ComparisonTable, { key: 'comparison-table' }), \r\n \r\n React.createElement(Roadmap, { key: 'roadmap' }),\r\n ])\r\n ]);\r\n }\r\n \r\n if (mode === 'create') {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'create-flow',\r\n className: \"w-full max-w-3xl space-y-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"text-center\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'back',\r\n onClick: resetToSelect,\r\n className: \"mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-arrow-left mr-2'\r\n }),\r\n 'Back to selection'\r\n ]),\r\n React.createElement('h2', {\r\n key: 'title',\r\n className: \"text-xl font-semibold text-primary mb-2\"\r\n }, 'Creating a secure channel')\r\n ]),\r\n \r\n // Step 1\r\n React.createElement('div', {\r\n key: 'step1',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"step-number mr-3\"\r\n }, '1'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Generating ECDH keys and verification code\")\r\n ]),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm mb-4\"\r\n }, \"Creating cryptographically strong keys and codes to protect against attacks\"),\r\n React.createElement('button', {\r\n key: 'create-btn',\r\n onClick: onCreateOffer,\r\n disabled: connectionStatus === 'connecting' || showOfferStep,\r\n className: `w-full btn-primary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed`\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt mr-2'\r\n }),\r\n showOfferStep ? 'Keys created \u2713' : 'Create secure keys'\r\n ]),\r\n \r\n showOfferStep && React.createElement('div', {\r\n key: 'offer-result',\r\n className: \"mt-6 space-y-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'success',\r\n className: \"p-3 bg-green-500/10 border border-green-500/20 rounded-lg\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-green-400 text-sm font-medium flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-check-circle mr-2'\r\n }),\r\n 'Secure invitation created! Send the code to your contact:'\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'offer-data',\r\n className: \"space-y-3\"\r\n }, [\r\n React.createElement('textarea', {\r\n key: 'textarea',\r\n value: typeof offerData === 'object' ? JSON.stringify(offerData, null, 2) : offerData,\r\n readOnly: true,\r\n rows: 8,\r\n className: \"w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg font-mono text-xs text-secondary resize-none custom-scrollbar\"\r\n }),\r\n React.createElement(EnhancedCopyButton, {\r\n key: 'copy',\r\n text: typeof offerData === 'object' ? JSON.stringify(offerData, null, 2) : offerData,\r\n className: \"w-full px-3 py-2 bg-orange-500/10 hover:bg-orange-500/20 text-orange-400 border border-orange-500/20 rounded text-sm font-medium\"\r\n }, 'Copy invitation code')\r\n ])\r\n ])\r\n ]),\r\n \r\n // Step 2 - Session Type Selection\r\n // showOfferStep && React.createElement('div', {\r\n // key: 'step2',\r\n // className: \"card-minimal rounded-xl p-6\"\r\n // }, [\r\n // React.createElement('div', {\r\n // key: 'step-header',\r\n // className: \"flex items-center mb-4\"\r\n // }, [\r\n // React.createElement('div', {\r\n // key: 'number',\r\n // className: \"w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3\"\r\n // }, '2'),\r\n // React.createElement('h3', {\r\n // key: 'title',\r\n // className: \"text-lg font-medium text-primary\"\r\n // }, \"Select session type\")\r\n // ]),\r\n // React.createElement('p', {\r\n // key: 'description',\r\n // className: \"text-secondary text-sm mb-4\"\r\n // }, \"Choose a session plan or use limited demo mode for testing.\"),\r\n // React.createElement(SessionTypeSelector, {\r\n // key: 'session-selector',\r\n // onSelectType: (sessionType) => {\r\n // // Save the selected session type\r\n // setSelectedSessionType(sessionType);\r\n // console.log('\uD83C\uDFAF Session type selected:', sessionType);\r\n \r\n // // FIX: For demo sessions, we immediately call automatic activation\r\n // if (sessionType === 'demo') {\r\n // console.log('\uD83C\uDFAE Demo session selected, scheduling automatic activation...');\r\n // // Delay activation for 2 seconds to stabilize\r\n // setTimeout(() => {\r\n // if (sessionManager) {\r\n // console.log('\uD83D\uDE80 Triggering demo session activation from selection...');\r\n // handleDemoVerification();\r\n // }\r\n // }, 2000);\r\n // }\r\n \r\n // // Open a modal payment window\r\n // if (typeof window.showPaymentModal === 'function') {\r\n // window.showPaymentModal(sessionType);\r\n // } else {\r\n // // Fallback - show session information\r\n // console.log('Selected session type:', sessionType);\r\n // }\r\n // },\r\n // onCancel: resetToSelect,\r\n // sessionManager: window.sessionManager\r\n // })\r\n // ]),\r\n \r\n // Step 3 - Waiting for response\r\n showOfferStep && React.createElement('div', {\r\n key: 'step2',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"w-8 h-8 bg-blue-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3\"\r\n }, '2'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Waiting for the peer's response\")\r\n ]),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm mb-4\"\r\n }, \"Paste the encrypted invitation code from your contact.\"),\r\n React.createElement('textarea', {\r\n key: 'input',\r\n value: answerInput,\r\n onChange: (e) => setAnswerInput(e.target.value),\r\n rows: 6,\r\n placeholder: \"Paste the encrypted response code from your contact...\",\r\n className: \"w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-orange-500/40 focus:outline-none transition-all custom-scrollbar text-sm\"\r\n }),\r\n React.createElement('button', {\r\n key: 'connect-btn',\r\n onClick: onConnect,\r\n disabled: !answerInput.trim(),\r\n className: \"w-full btn-secondary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-rocket mr-2'\r\n }),\r\n 'Establish connection'\r\n ])\r\n ])\r\n ])\r\n ]);\r\n }\r\n \r\n if (mode === 'join') {\r\n return React.createElement('div', {\r\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'join-flow',\r\n className: \"w-full max-w-3xl space-y-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'header',\r\n className: \"text-center\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'back',\r\n onClick: resetToSelect,\r\n className: \"mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-arrow-left mr-2'\r\n }),\r\n 'Back to selection'\r\n ]),\r\n React.createElement('h2', {\r\n key: 'title',\r\n className: \"text-xl font-semibold text-primary mb-2\"\r\n }, 'Joining the secure channel')\r\n ]),\r\n \r\n // Step 1\r\n React.createElement('div', {\r\n key: 'step1',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3\"\r\n }, '1'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Paste secure invitation\")\r\n ]),\r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm mb-4\"\r\n }, \"Copy and paste the encrypted invitation code from the initiator.\"),\r\n React.createElement('textarea', {\r\n key: 'input',\r\n value: offerInput,\r\n onChange: (e) => setOfferInput(e.target.value),\r\n rows: 8,\r\n placeholder: \"Paste the encrypted invitation code...\",\r\n className: \"w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm\"\r\n }),\r\n React.createElement('button', {\r\n key: 'process-btn',\r\n onClick: onCreateAnswer,\r\n disabled: !offerInput.trim() || connectionStatus === 'connecting',\r\n className: \"w-full btn-secondary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-cogs mr-2'\r\n }),\r\n 'Process the invitation'\r\n ])\r\n ]),\r\n \r\n // Step 2\r\n showAnswerStep && React.createElement('div', {\r\n key: 'step2',\r\n className: \"card-minimal rounded-xl p-6\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'step-header',\r\n className: \"flex items-center mb-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'number',\r\n className: \"step-number mr-3\"\r\n }, '2'),\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: \"text-lg font-medium text-primary\"\r\n }, \"Sending a secure response\")\r\n ]),\r\n React.createElement('div', {\r\n key: 'success',\r\n className: \"p-3 bg-green-500/10 border border-green-500/20 rounded-lg mb-4\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-green-400 text-sm font-medium flex items-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-check-circle mr-2'\r\n }),\r\n 'Secure response created! Send this code to the initiator:'\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'answer-data',\r\n className: \"space-y-3 mb-4\"\r\n }, [\r\n React.createElement('textarea', {\r\n key: 'textarea',\r\n value: typeof answerData === 'object' ? JSON.stringify(answerData, null, 2) : answerData,\r\n readOnly: true,\r\n rows: 6,\r\n className: \"w-full p-3 bg-custom-bg border border-green-500/20 rounded-lg font-mono text-xs text-secondary resize-none custom-scrollbar\"\r\n }),\r\n React.createElement(EnhancedCopyButton, {\r\n key: 'copy',\r\n text: typeof answerData === 'object' ? JSON.stringify(answerData, null, 2) : answerData,\r\n className: \"w-full px-3 py-2 bg-green-500/10 hover:bg-green-500/20 text-green-400 border border-green-500/20 rounded text-sm font-medium\"\r\n }, 'Copy response code')\r\n ]),\r\n React.createElement('div', {\r\n key: 'info',\r\n className: \"p-3 bg-purple-500/10 border border-purple-500/20 rounded-lg\"\r\n }, [\r\n React.createElement('p', {\r\n className: \"text-purple-400 text-sm flex items-center justify-center\"\r\n }, [\r\n React.createElement('i', {\r\n className: 'fas fa-shield-alt mr-2'\r\n }),\r\n 'The connection will be established with verification'\r\n ])\r\n ])\r\n ])\r\n ])\r\n ]);\r\n }\r\n };\r\n \r\n const EnhancedChatInterface = ({\r\n messages,\r\n messageInput,\r\n setMessageInput,\r\n onSendMessage,\r\n onDisconnect,\r\n keyFingerprint,\r\n isVerified,\r\n chatMessagesRef,\r\n scrollToBottom,\r\n webrtcManager\r\n }) => {\r\n const [showScrollButton, setShowScrollButton] = React.useState(false);\r\n const [showFileTransfer, setShowFileTransfer] = React.useState(false);\r\n \r\n // \u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0430\u044F \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0430 \u043F\u0440\u0438 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0438 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439\r\n React.useEffect(() => {\r\n if (chatMessagesRef.current && messages.length > 0) {\r\n const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current;\r\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\r\n if (isNearBottom) {\r\n const smoothScroll = () => {\r\n if (chatMessagesRef.current) {\r\n chatMessagesRef.current.scrollTo({\r\n top: chatMessagesRef.current.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n };\r\n smoothScroll();\r\n setTimeout(smoothScroll, 50);\r\n setTimeout(smoothScroll, 150);\r\n }\r\n }\r\n }, [messages, chatMessagesRef]);\r\n \r\n // \u041E\u0431\u0440\u0430\u0431\u043E\u0442\u0447\u0438\u043A \u0441\u043A\u0440\u043E\u043B\u043B\u0430\r\n const handleScroll = () => {\r\n if (chatMessagesRef.current) {\r\n const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current;\r\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\r\n setShowScrollButton(!isNearBottom);\r\n }\r\n };\r\n \r\n // \u041F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0430 \u0432\u043D\u0438\u0437 \u043F\u043E \u043A\u043D\u043E\u043F\u043A\u0435\r\n const handleScrollToBottom = () => {\r\n scrollToBottom();\r\n setShowScrollButton(false);\r\n };\r\n \r\n // \u041E\u0431\u0440\u0430\u0431\u043E\u0442\u0447\u0438\u043A \u043D\u0430\u0436\u0430\u0442\u0438\u044F Enter\r\n const handleKeyPress = (e) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n onSendMessage();\r\n }\r\n };\r\n \r\n // \u0418\u0421\u041F\u0420\u0410\u0412\u041B\u0415\u041D\u0418\u0415: \u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u0434\u043B\u044F \u0444\u0430\u0439\u043B\u043E\u0432\u044B\u0445 \u0442\u0440\u0430\u043D\u0441\u0444\u0435\u0440\u043E\u0432\r\n const isFileTransferReady = () => {\r\n if (!webrtcManager) return false;\r\n \r\n const connected = webrtcManager.isConnected ? webrtcManager.isConnected() : false;\r\n const verified = webrtcManager.isVerified || false;\r\n const hasDataChannel = webrtcManager.dataChannel && webrtcManager.dataChannel.readyState === 'open';\r\n \r\n return connected && verified && hasDataChannel;\r\n };\r\n \r\n // \u0412\u043E\u0437\u0432\u0440\u0430\u0442 JSX \u0447\u0435\u0440\u0435\u0437 React.createElement\r\n return React.createElement(\r\n 'div',\r\n {\r\n className: \"chat-container flex flex-col\",\r\n style: { backgroundColor: '#272827', height: 'calc(100vh - 64px)' }\r\n },\r\n [\r\n // \u041E\u0431\u043B\u0430\u0441\u0442\u044C \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439\r\n React.createElement(\r\n 'div',\r\n { className: \"flex-1 flex flex-col overflow-hidden\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"flex-1 max-w-4xl mx-auto w-full p-4 overflow-hidden\" },\r\n React.createElement(\r\n 'div',\r\n {\r\n ref: chatMessagesRef,\r\n onScroll: handleScroll,\r\n className: \"h-full overflow-y-auto space-y-3 hide-scrollbar pr-2 scroll-smooth\"\r\n },\r\n messages.length === 0 ?\r\n React.createElement(\r\n 'div',\r\n { className: \"flex items-center justify-center h-full\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"text-center max-w-md\" },\r\n [\r\n React.createElement(\r\n 'div',\r\n { className: \"w-16 h-16 bg-green-500/10 border border-green-500/20 rounded-xl flex items-center justify-center mx-auto mb-4\" },\r\n React.createElement(\r\n 'svg',\r\n { className: \"w-8 h-8 text-green-500\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z\"\r\n })\r\n )\r\n ),\r\n React.createElement('h3', { className: \"text-lg font-medium text-gray-300 mb-2\" }, \"Secure channel is ready!\"),\r\n React.createElement('p', { className: \"text-gray-400 text-sm mb-4\" }, \"All messages are protected by modern cryptographic algorithms\"),\r\n React.createElement(\r\n 'div',\r\n { className: \"text-left space-y-2\" },\r\n [\r\n ['End-to-end encryption', 'M5 13l4 4L19 7'],\r\n ['Protection against replay attacks', 'M5 13l4 4L19 7'],\r\n ['Integrity verification', 'M5 13l4 4L19 7'],\r\n ['Perfect Forward Secrecy', 'M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15']\r\n ].map(([text, d], i) =>\r\n React.createElement(\r\n 'div',\r\n { key: `f${i}`, className: \"flex items-center text-sm text-gray-400\" },\r\n [\r\n React.createElement(\r\n 'svg',\r\n {\r\n className: `w-4 h-4 mr-3 ${i === 3 ? 'text-purple-500' : 'text-green-500'}`,\r\n fill: \"none\",\r\n stroke: \"currentColor\",\r\n viewBox: \"0 0 24 24\"\r\n },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: d\r\n })\r\n ),\r\n text\r\n ]\r\n )\r\n )\r\n )\r\n ]\r\n )\r\n ) :\r\n messages.map((msg) =>\r\n React.createElement(EnhancedChatMessage, {\r\n key: msg.id,\r\n message: msg.message,\r\n type: msg.type,\r\n timestamp: msg.timestamp\r\n })\r\n )\r\n )\r\n )\r\n ),\r\n \r\n // \u041A\u043D\u043E\u043F\u043A\u0430 \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0438 \u0432\u043D\u0438\u0437\r\n showScrollButton &&\r\n React.createElement(\r\n 'button',\r\n {\r\n onClick: handleScrollToBottom,\r\n className: \"fixed right-6 w-12 h-12 bg-green-500/20 hover:bg-green-500/30 border border-green-500/30 text-green-400 rounded-full flex items-center justify-center transition-all duration-200 shadow-lg z-50\",\r\n style: { bottom: '160px' }\r\n },\r\n React.createElement(\r\n 'svg',\r\n { className: \"w-6 h-6\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M19 14l-7 7m0 0l-7-7m7 7V3\"\r\n })\r\n )\r\n ),\r\n \r\n // \u0421\u0435\u043A\u0446\u0438\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0444\u0430\u0439\u043B\u043E\u0432\r\n React.createElement(\r\n 'div',\r\n {\r\n className: \"flex-shrink-0 border-t border-gray-500/10\",\r\n style: { backgroundColor: '#272827' }\r\n },\r\n React.createElement(\r\n 'div',\r\n { className: \"max-w-4xl mx-auto px-4\" },\r\n [\r\n React.createElement(\r\n 'button',\r\n {\r\n onClick: () => setShowFileTransfer(!showFileTransfer),\r\n className: `flex items-center text-sm text-gray-400 hover:text-gray-300 transition-colors py-4 ${showFileTransfer ? 'mb-4' : ''}`\r\n },\r\n [\r\n React.createElement(\r\n 'svg',\r\n {\r\n className: `w-4 h-4 mr-2 transform transition-transform ${showFileTransfer ? 'rotate-180' : ''}`,\r\n fill: \"none\",\r\n stroke: \"currentColor\",\r\n viewBox: \"0 0 24 24\"\r\n },\r\n showFileTransfer ?\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M5 15l7-7 7 7\"\r\n }) :\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13\"\r\n })\r\n ),\r\n showFileTransfer ? 'Hide file transfer' : 'Send files'\r\n ]\r\n ),\r\n // \u0418\u0421\u041F\u0420\u0410\u0412\u041B\u0415\u041D\u0418\u0415: \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u043C \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u044B\u0439 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\r\n showFileTransfer &&\r\n React.createElement(window.FileTransferComponent || (() => \r\n React.createElement('div', {\r\n className: \"p-4 text-center text-red-400\"\r\n }, 'FileTransferComponent not loaded')\r\n ), {\r\n webrtcManager: webrtcManager,\r\n isConnected: isFileTransferReady()\r\n })\r\n ]\r\n )\r\n ),\r\n \r\n // \u041E\u0431\u043B\u0430\u0441\u0442\u044C \u0432\u0432\u043E\u0434\u0430 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439\r\n React.createElement(\r\n 'div',\r\n { className: \"border-t border-gray-500/10\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"max-w-4xl mx-auto p-4\" },\r\n React.createElement(\r\n 'div',\r\n { className: \"flex items-stretch space-x-3\" },\r\n [\r\n React.createElement(\r\n 'div',\r\n { className: \"flex-1 relative\" },\r\n [\r\n React.createElement('textarea', {\r\n value: messageInput,\r\n onChange: (e) => setMessageInput(e.target.value),\r\n onKeyDown: handleKeyPress,\r\n placeholder: \"Enter message to encrypt...\",\r\n rows: 2,\r\n maxLength: 2000,\r\n style: { backgroundColor: '#272827' },\r\n className: \"w-full p-3 border border-gray-600 rounded-lg resize-none text-gray-300 placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm\"\r\n }),\r\n React.createElement(\r\n 'div',\r\n { className: \"absolute bottom-2 right-3 flex items-center space-x-2 text-xs text-gray-400\" },\r\n [\r\n React.createElement('span', null, `${messageInput.length}/2000`),\r\n React.createElement('span', null, \"\u2022 Enter to send\")\r\n ]\r\n )\r\n ]\r\n ),\r\n React.createElement(\r\n 'button',\r\n {\r\n onClick: onSendMessage,\r\n disabled: !messageInput.trim(),\r\n className: \"bg-green-400/20 text-green-400 p-3 rounded-lg transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center min-h-[72px]\"\r\n },\r\n React.createElement(\r\n 'svg',\r\n { className: \"w-6 h-6\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\r\n React.createElement('path', {\r\n strokeLinecap: \"round\",\r\n strokeLinejoin: \"round\",\r\n strokeWidth: 2,\r\n d: \"M12 19l9 2-9-18-9 18 9-2zm0 0v-8\"\r\n })\r\n )\r\n )\r\n ]\r\n )\r\n )\r\n )\r\n ]\r\n );\r\n };\r\n \r\n \r\n // Main Enhanced Application Component\r\n const EnhancedSecureP2PChat = () => {\r\n const [messages, setMessages] = React.useState([]);\r\n const [connectionStatus, setConnectionStatus] = React.useState('disconnected');\r\n \r\n React.useEffect(() => {\r\n if (messages.length > 0 && chatMessagesRef.current) {\r\n const scrollToBottom = () => {\r\n if (chatMessagesRef.current) {\r\n chatMessagesRef.current.scrollTo({\r\n top: chatMessagesRef.current.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n };\r\n \r\n scrollToBottom();\r\n setTimeout(scrollToBottom, 50);\r\n setTimeout(scrollToBottom, 150);\r\n }\r\n }, [messages]);\r\n const [messageInput, setMessageInput] = React.useState('');\r\n const [offerData, setOfferData] = React.useState('');\r\n const [answerData, setAnswerData] = React.useState('');\r\n const [offerInput, setOfferInput] = React.useState('');\r\n const [answerInput, setAnswerInput] = React.useState('');\r\n const [keyFingerprint, setKeyFingerprint] = React.useState('');\r\n const [verificationCode, setVerificationCode] = React.useState('');\r\n const [showOfferStep, setShowOfferStep] = React.useState(false);\r\n const [showAnswerStep, setShowAnswerStep] = React.useState(false);\r\n const [showVerification, setShowVerification] = React.useState(false);\r\n const [isVerified, setIsVerified] = React.useState(false);\r\n const [securityLevel, setSecurityLevel] = React.useState(null);\r\n \r\n // Mutual verification states\r\n const [localVerificationConfirmed, setLocalVerificationConfirmed] = React.useState(false);\r\n const [remoteVerificationConfirmed, setRemoteVerificationConfirmed] = React.useState(false);\r\n const [bothVerificationsConfirmed, setBothVerificationsConfirmed] = React.useState(false);\r\n \r\n // PAKE password states removed - using SAS verification instead\r\n \r\n // Pay-per-session state\r\n const [sessionManager, setSessionManager] = React.useState(null);\r\n const [showPaymentModal, setShowPaymentModal] = React.useState(false);\r\n const [sessionTimeLeft, setSessionTimeLeft] = React.useState(0);\r\n const [pendingSession, setPendingSession] = React.useState(null); // { type, preimage }\r\n const [selectedSessionType, setSelectedSessionType] = React.useState(null); // 'demo', 'basic', 'premium'\r\n \r\n // Initialize sessionManager after loading modules\r\n React.useEffect(() => {\r\n if (window.PayPerSessionManager && !sessionManager) {\r\n console.log('\uD83D\uDCB0 Initializing PayPerSessionManager...');\r\n const newSessionManager = new window.PayPerSessionManager();\r\n setSessionManager(newSessionManager);\r\n window.sessionManager = newSessionManager;\r\n console.log('\u2705 PayPerSessionManager initialized successfully');\r\n }\r\n }, [sessionManager]);\r\n \r\n \r\n \r\n // Global functions for accessing modal windows\r\n React.useEffect(() => {\r\n if (!sessionManager) return; \r\n \r\n window.showPaymentModal = (sessionType) => {\r\n setShowPaymentModal(true);\r\n // Pass the selected session type to the modal window\r\n if (sessionType) {\r\n console.log('Opening payment modal for session type:', sessionType);\r\n }\r\n };\r\n window.sessionManager = sessionManager;\r\n window.forceCleanup = () => {\r\n handleClearData();\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n if (sessionManager) {\r\n sessionManager.cleanup();\r\n }\r\n };\r\n \r\n window.forceSessionReset = () => {\r\n if (sessionManager) {\r\n sessionManager.resetSession();\r\n }\r\n setSessionTimeLeft(0);\r\n };\r\n \r\n window.forceSessionCleanup = () => {\r\n if (sessionManager) {\r\n sessionManager.cleanup();\r\n }\r\n setSessionTimeLeft(0);\r\n setSessionManager(null);\r\n };\r\n \r\n window.clearLogs = () => {\r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n };\r\n \r\n return () => {\r\n delete window.showPaymentModal;\r\n delete window.sessionManager;\r\n delete window.forceCleanup;\r\n delete window.forceSessionReset;\r\n delete window.forceSessionCleanup;\r\n delete window.clearLogs;\r\n };\r\n }, [sessionManager]);\r\n \r\n const webrtcManagerRef = React.useRef(null);\r\n // Expose for modules/UI that run outside this closure (e.g., inline handlers)\r\n // Safe because it's a ref object and we maintain it centrally here\r\n window.webrtcManagerRef = webrtcManagerRef;\r\n \r\n const addMessageWithAutoScroll = React.useCallback((message, type) => {\r\n const newMessage = {\r\n message,\r\n type,\r\n id: Date.now() + Math.random(),\r\n timestamp: Date.now()\r\n };\r\n \r\n setMessages(prev => {\r\n const updated = [...prev, newMessage];\r\n \r\n setTimeout(() => {\r\n if (chatMessagesRef?.current) {\r\n const container = chatMessagesRef.current;\r\n try {\r\n const { scrollTop, scrollHeight, clientHeight } = container;\r\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\r\n \r\n if (isNearBottom || prev.length === 0) {\r\n requestAnimationFrame(() => {\r\n if (container && container.scrollTo) {\r\n container.scrollTo({\r\n top: container.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n });\r\n }\r\n } catch (error) {\r\n console.warn('Scroll error:', error);\r\n container.scrollTop = container.scrollHeight;\r\n }\r\n }\r\n }, 50);\r\n \r\n return updated;\r\n });\r\n }, []);\r\n \r\n // Update security level based on real verification\r\n const updateSecurityLevel = React.useCallback(async () => {\r\n if (window.isUpdatingSecurity) {\r\n return;\r\n }\r\n \r\n window.isUpdatingSecurity = true;\r\n \r\n try {\r\n if (webrtcManagerRef.current) {\r\n const level = await webrtcManagerRef.current.calculateSecurityLevel();\r\n setSecurityLevel(level);\r\n \r\n if (window.DEBUG_MODE) {\r\n console.log('\uD83D\uDD12 Security level updated:', {\r\n level: level.level,\r\n score: level.score,\r\n sessionType: level.sessionType,\r\n passedChecks: level.passedChecks,\r\n totalChecks: level.totalChecks\r\n });\r\n }\r\n }\r\n } catch (error) {\r\n console.error('Failed to update security level:', error);\r\n setSecurityLevel({\r\n level: 'ERROR',\r\n score: 0,\r\n color: 'red',\r\n details: 'Verification failed'\r\n });\r\n } finally {\r\n setTimeout(() => {\r\n window.isUpdatingSecurity = false;\r\n }, 2000);\r\n }\r\n }, []);\r\n \r\n // Session time ticker\r\n React.useEffect(() => {\r\n if (!sessionManager) return; \r\n \r\n const timer = setInterval(() => {\r\n if (sessionManager.hasActiveSession()) {\r\n setSessionTimeLeft(sessionManager.getTimeLeft());\r\n } else {\r\n setSessionTimeLeft(0);\r\n }\r\n }, 1000);\r\n return () => clearInterval(timer);\r\n }, [sessionManager]);\r\n \r\n // Session expiration handler\r\n React.useEffect(() => {\r\n if (!sessionManager) return; \r\n \r\n sessionManager.onSessionExpired = () => {\r\n setMessages(prev => [...prev, {\r\n message: '\u23F0 Session time expired. The connection will be terminated.',\r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n setTimeout(() => handleDisconnect(), 3000);\r\n };\r\n }, [sessionManager]);\r\n \r\n // Automatic activation of demo session after successful verification\r\n React.useEffect(() => {\r\n if (!sessionManager) return;\r\n \r\n // Listen to demo session verification events\r\n const handleDemoVerification = async () => {\r\n try {\r\n // Check if there is an active demo session\r\n if (sessionManager.hasActiveSession()) {\r\n console.log('\u2705 Demo session already active');\r\n return;\r\n }\r\n \r\n // Diagnose sessionManager state\r\n console.log('\uD83D\uDD0D SessionManager state before activation:', {\r\n hasActiveSession: sessionManager.hasActiveSession(),\r\n timeLeft: sessionManager.getTimeLeft(),\r\n currentSession: sessionManager.currentSession\r\n });\r\n \r\n window.pendingDemoActivation = true;\r\n \r\n setTimeout(async () => {\r\n if (window.pendingDemoActivation && sessionManager) {\r\n let result = null;\r\n \r\n const demoSession = sessionManager.createDemoSessionForActivation();\r\n \r\n if (!demoSession.success) {\r\n return;\r\n }\r\n \r\n result = await sessionManager.safeActivateSession(\r\n 'demo', \r\n demoSession.preimage, \r\n demoSession.paymentHash\r\n );\r\n \r\n if (result && result.success) {\r\n setSessionTimeLeft(sessionManager.getTimeLeft());\r\n \r\n setMessages(prev => [...prev, {\r\n message: `\uD83C\uDFAE Demo session activated for ${Math.round(result.timeLeft / 60000)} minutes`,\r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n window.pendingDemoActivation = false;\r\n } else {\r\n window.pendingDemoActivation = false;\r\n }\r\n }\r\n }, 3000); \r\n } catch (error) {\r\n console.error('\u274C Error activating demo session automatically:', error);\r\n }\r\n };\r\n \r\n if (connectionStatus === 'connected' && isVerified) {\r\n setTimeout(handleDemoVerification, 1000);\r\n }\r\n \r\n if (selectedSessionType === 'demo' && connectionStatus === 'connected' && isVerified) {\r\n setTimeout(handleDemoVerification, 1000);\r\n }\r\n \r\n }, [sessionManager, connectionStatus, isVerified, selectedSessionType]);\r\n const chatMessagesRef = React.useRef(null);\r\n \r\n // Scroll down function\r\n const scrollToBottom = () => {\r\n if (chatMessagesRef.current) {\r\n const scrollAttempt = () => {\r\n if (chatMessagesRef.current) {\r\n chatMessagesRef.current.scrollTo({\r\n top: chatMessagesRef.current.scrollHeight,\r\n behavior: 'smooth'\r\n });\r\n }\r\n };\r\n scrollAttempt();\r\n \r\n setTimeout(scrollAttempt, 50);\r\n setTimeout(scrollAttempt, 150);\r\n setTimeout(scrollAttempt, 300);\r\n \r\n requestAnimationFrame(() => {\r\n setTimeout(scrollAttempt, 100);\r\n });\r\n }\r\n };\r\n \r\n // PAKE password functions removed - using SAS verification instead\r\n \r\n React.useEffect(() => {\r\n // Prevent multiple initializations\r\n if (webrtcManagerRef.current) {\r\n console.log('\u26A0\uFE0F WebRTC Manager already initialized, skipping...');\r\n return;\r\n }\r\n \r\n const handleMessage = (message, type) => {\r\n // \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043D\u0430 \u0444\u0430\u0439\u043B\u043E\u0432\u044B\u0435 \u0438 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u044B\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u044F\r\n if (typeof message === 'string' && message.trim().startsWith('{')) {\r\n try {\r\n const parsedMessage = JSON.parse(message);\r\n const blockedTypes = [\r\n 'file_transfer_start',\r\n 'file_transfer_response',\r\n 'file_chunk',\r\n 'chunk_confirmation',\r\n 'file_transfer_complete',\r\n 'file_transfer_error',\r\n 'heartbeat',\r\n 'verification',\r\n 'verification_response',\r\n 'verification_confirmed',\r\n 'verification_both_confirmed',\r\n 'peer_disconnect',\r\n 'key_rotation_signal',\r\n 'key_rotation_ready',\r\n 'security_upgrade'\r\n ];\r\n if (parsedMessage.type && blockedTypes.includes(parsedMessage.type)) {\r\n console.log(`\uD83D\uDED1 Blocked system/file message from chat: ${parsedMessage.type}`);\r\n return; // \u041D\u0435 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u044B\u0435 \u0438 \u0444\u0430\u0439\u043B\u043E\u0432\u044B\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u044F \u0432 \u0447\u0430\u0442\u0435\r\n }\r\n } catch (parseError) {\r\n // \u041D\u0435 JSON - \u044D\u0442\u043E \u043D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E \u0434\u043B\u044F \u043E\u0431\u044B\u0447\u043D\u044B\u0445 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u044B\u0445 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439\r\n }\r\n }\r\n \r\n addMessageWithAutoScroll(message, type);\r\n };\r\n \r\n const handleStatusChange = (status) => {\r\n console.log('handleStatusChange called with status:', status);\r\n setConnectionStatus(status);\r\n \r\n if (status === 'connected') {\r\n document.dispatchEvent(new CustomEvent('new-connection'));\r\n \r\n // \u041D\u0435 \u0441\u043A\u0440\u044B\u0432\u0430\u0435\u043C \u0432\u0435\u0440\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E \u043F\u0440\u0438 'connected' - \u0442\u043E\u043B\u044C\u043A\u043E \u043F\u0440\u0438 'verified'\r\n // setIsVerified(true);\r\n // setShowVerification(false);\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'verifying') {\r\n console.log('Setting showVerification to true for verifying status');\r\n setShowVerification(true);\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'verified') {\r\n setIsVerified(true);\r\n setShowVerification(false);\r\n setBothVerificationsConfirmed(true);\r\n // CRITICAL: Set connectionStatus to 'connected' to show chat\r\n setConnectionStatus('connected');\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'connecting') {\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } else if (status === 'disconnected') {\r\n // \u041F\u0440\u0438 \u0440\u0430\u0437\u0440\u044B\u0432\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u044F \u043E\u0447\u0438\u0449\u0430\u0435\u043C \u0432\u0441\u0435 \u0434\u0430\u043D\u043D\u044B\u0435\r\n setConnectionStatus('disconnected');\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n \r\n // Dispatch disconnected event for SessionTimer\r\n document.dispatchEvent(new CustomEvent('disconnected'));\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // Clear connection data\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n \r\n // Reset session and timer\r\n if (sessionManager && sessionManager.hasActiveSession()) {\r\n sessionManager.resetSession();\r\n setSessionTimeLeft(0);\r\n setHasActiveSession(false);\r\n }\r\n \r\n // Return to main page after a short delay\r\n setTimeout(() => {\r\n setConnectionStatus('disconnected');\r\n setShowVerification(false);\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setMessages([]);\r\n }, 1000);\r\n \r\n // \u041D\u0435 \u043E\u0447\u0438\u0449\u0430\u0435\u043C \u043A\u043E\u043D\u0441\u043E\u043B\u044C \u043F\u0440\u0438 \u0440\u0430\u0437\u0440\u044B\u0432\u0435 \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u044F\r\n // \u0447\u0442\u043E\u0431\u044B \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C \u043C\u043E\u0433 \u0432\u0438\u0434\u0435\u0442\u044C \u043E\u0448\u0438\u0431\u043A\u0438\r\n } else if (status === 'peer_disconnected') {\r\n if (sessionManager && sessionManager.hasActiveSession()) {\r\n sessionManager.resetSession();\r\n setSessionTimeLeft(0);\r\n setHasActiveSession(false);\r\n }\r\n \r\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\r\n \r\n // A short delay before clearing to display the status\r\n setTimeout(() => {\r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n setConnectionStatus('disconnected');\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // Clear connection data\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setMessages([]);\r\n \r\n // \u041D\u0435 \u043E\u0447\u0438\u0449\u0430\u0435\u043C \u043A\u043E\u043D\u0441\u043E\u043B\u044C \u043F\u0440\u0438 \u043E\u0442\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0438 \u043F\u0438\u0440\u0430\r\n // \u0447\u0442\u043E\u0431\u044B \u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0438\u0441\u0442\u043E\u0440\u0438\u044E \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u044F\r\n // if (typeof console.clear === 'function') {\r\n // console.clear();\r\n // }\r\n \r\n setSessionManager(null);\r\n }, 2000);\r\n }\r\n };\r\n \r\n const handleKeyExchange = (fingerprint) => {\r\n console.log('handleKeyExchange called with fingerprint:', fingerprint);\r\n if (fingerprint === '') {\r\n setKeyFingerprint('');\r\n } else {\r\n setKeyFingerprint(fingerprint);\r\n console.log('Key fingerprint set in UI:', fingerprint);\r\n }\r\n };\r\n \r\n const handleVerificationRequired = (code) => {\r\n console.log('handleVerificationRequired called with code:', code);\r\n if (code === '') {\r\n setVerificationCode('');\r\n setShowVerification(false);\r\n } else {\r\n setVerificationCode(code);\r\n setShowVerification(true);\r\n console.log('Verification code set, showing verification UI');\r\n }\r\n };\r\n \r\n const handleVerificationStateChange = (state) => {\r\n console.log('handleVerificationStateChange called with state:', state);\r\n setLocalVerificationConfirmed(state.localConfirmed);\r\n setRemoteVerificationConfirmed(state.remoteConfirmed);\r\n setBothVerificationsConfirmed(state.bothConfirmed);\r\n };\r\n \r\n // Callback for handling response errors\r\n const handleAnswerError = (errorType, errorMessage) => {\r\n if (errorType === 'replay_attack') {\r\n // Reset the session upon replay attack\r\n if (sessionManager.hasActiveSession()) {\r\n sessionManager.resetSession();\r\n setSessionTimeLeft(0);\r\n }\r\n setPendingSession(null);\r\n \r\n addMessageWithAutoScroll('\uD83D\uDCA1 Data is outdated. Please create a new invitation or use a current response code.', 'system');\r\n \r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n } else if (errorType === 'security_violation') {\r\n // Reset the session upon security breach\r\n if (sessionManager.hasActiveSession()) {\r\n sessionManager.resetSession();\r\n setSessionTimeLeft(0);\r\n }\r\n setPendingSession(null);\r\n \r\n addMessageWithAutoScroll(`\uD83D\uDD12 Security breach: ${errorMessage}`, 'system');\r\n \r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n }\r\n };\r\n \r\n // Create WebRTC Manager only once\r\n console.log('\uD83D\uDD27 Initializing WebRTC Manager...');\r\n \r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n \r\n webrtcManagerRef.current = new EnhancedSecureWebRTCManager(\r\n handleMessage, \r\n handleStatusChange, \r\n handleKeyExchange,\r\n handleVerificationRequired,\r\n handleAnswerError,\r\n handleVerificationStateChange\r\n );\r\n \r\n handleMessage('\uD83D\uDE80 SecureBit.chat Enhanced Security Edition v4.02.985 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.', 'system');\r\n \r\n const handleBeforeUnload = (event) => {\r\n if (event.type === 'beforeunload' && !isTabSwitching) {\r\n console.log('\uD83D\uDD0C Page unloading (closing tab) - sending disconnect notification');\r\n \r\n if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) {\r\n try {\r\n webrtcManagerRef.current.sendSystemMessage({\r\n type: 'peer_disconnect',\r\n reason: 'user_disconnect',\r\n timestamp: Date.now()\r\n });\r\n } catch (error) {\r\n console.log('Could not send disconnect notification:', error.message);\r\n }\r\n \r\n setTimeout(() => {\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n }, 100);\r\n } else if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n } else if (isTabSwitching) {\r\n console.log('\uD83D\uDCF1 Tab switching detected - NOT disconnecting');\r\n event.preventDefault();\r\n event.returnValue = '';\r\n }\r\n };\r\n \r\n window.addEventListener('beforeunload', handleBeforeUnload);\r\n \r\n let isTabSwitching = false;\r\n let tabSwitchTimeout = null;\r\n \r\n const handleVisibilityChange = () => {\r\n if (document.visibilityState === 'hidden') {\r\n console.log('\uD83D\uDCF1 Page hidden (tab switch) - keeping connection alive');\r\n isTabSwitching = true;\r\n \r\n if (tabSwitchTimeout) {\r\n clearTimeout(tabSwitchTimeout);\r\n }\r\n \r\n tabSwitchTimeout = setTimeout(() => {\r\n isTabSwitching = false;\r\n }, 5000); \r\n \r\n } else if (document.visibilityState === 'visible') {\r\n console.log('\uD83D\uDCF1 Page visible (tab restored) - connection maintained');\r\n isTabSwitching = false;\r\n \r\n if (tabSwitchTimeout) {\r\n clearTimeout(tabSwitchTimeout);\r\n tabSwitchTimeout = null;\r\n }\r\n }\r\n };\r\n \r\n document.addEventListener('visibilitychange', handleVisibilityChange);\r\n \r\n // Setup file transfer callbacks\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.setFileTransferCallbacks(\r\n // Progress callback\r\n (progress) => {\r\n console.log('File progress:', progress);\r\n },\r\n \r\n // File received callback\r\n (fileData) => {\r\n const sizeMb = Math.max(1, Math.round((fileData.fileSize || 0) / (1024 * 1024)));\r\n const downloadMessage = React.createElement('div', {\r\n className: 'flex items-center space-x-2'\r\n }, [\r\n React.createElement('span', { key: 'label' }, `\uD83D\uDCE5 File received: ${fileData.fileName} (${sizeMb} MB)`),\r\n React.createElement('button', {\r\n key: 'btn',\r\n className: 'px-3 py-1 rounded bg-blue-600 hover:bg-blue-700 text-white text-xs',\r\n onClick: async () => {\r\n try {\r\n const url = await fileData.getObjectURL();\r\n const a = document.createElement('a');\r\n a.href = url;\r\n a.download = fileData.fileName;\r\n a.click();\r\n // \u0414\u0430\u0435\u043C \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u0432\u0440\u0435\u043C\u044F \u043D\u0430\u0447\u0430\u0442\u044C \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0443, \u0437\u0430\u0442\u0435\u043C \u043E\u0441\u0432\u043E\u0431\u043E\u0436\u0434\u0430\u0435\u043C URL\r\n setTimeout(() => fileData.revokeObjectURL(url), 15000);\r\n } catch (e) {\r\n console.error('Download failed:', e);\r\n addMessageWithAutoScroll(`\u274C File upload error: ${String(e?.message || e)}`, 'system');\r\n }\r\n }\r\n }, 'Download')\r\n ]);\r\n \r\n addMessageWithAutoScroll(downloadMessage, 'system');\r\n },\r\n \r\n // Error callback\r\n (error) => {\r\n console.error('File transfer error:', error);\r\n \r\n if (error.includes('Connection not ready')) {\r\n addMessageWithAutoScroll(`\u26A0\uFE0F File transfer error: connection not ready. Try again later.`, 'system');\r\n } else if (error.includes('File too large')) {\r\n addMessageWithAutoScroll(`\u26A0\uFE0F File is too big. Maximum size: 100 MB`, 'system');\r\n } else {\r\n addMessageWithAutoScroll(`\u274C File transfer error: ${error}`, 'system');\r\n }\r\n }\r\n );\r\n }\r\n \r\n return () => {\r\n window.removeEventListener('beforeunload', handleBeforeUnload);\r\n document.removeEventListener('visibilitychange', handleVisibilityChange);\r\n \r\n if (tabSwitchTimeout) {\r\n clearTimeout(tabSwitchTimeout);\r\n tabSwitchTimeout = null;\r\n }\r\n \r\n if (webrtcManagerRef.current) {\r\n console.log('\uD83E\uDDF9 Cleaning up WebRTC Manager...');\r\n webrtcManagerRef.current.disconnect();\r\n webrtcManagerRef.current = null;\r\n }\r\n };\r\n }, []); // Empty dependency array to run only once\r\n \r\n const ensureActiveSessionOrPurchase = async () => {\r\n if (sessionManager.hasActiveSession()) return true;\r\n if (pendingSession) return true; \r\n setShowPaymentModal(true);\r\n return false;\r\n };\r\n \r\n const handleCreateOffer = async () => {\r\n try {\r\n console.log('\uD83C\uDFAF handleCreateOffer called');\r\n const ok = await ensureActiveSessionOrPurchase();\r\n if (!ok) return;\r\n \r\n setOfferData('');\r\n setShowOfferStep(false);\r\n \r\n console.log('\uD83C\uDFAF Calling createSecureOffer...');\r\n const offer = await webrtcManagerRef.current.createSecureOffer();\r\n console.log('\uD83C\uDFAF createSecureOffer returned:', offer ? 'success' : 'null');\r\n \r\n // Store offer data directly (no encryption needed with SAS)\r\n setOfferData(offer);\r\n setShowOfferStep(true);\r\n \r\n const existingMessages = messages.filter(m => \r\n m.type === 'system' && \r\n (m.message.includes('Secure invitation created') || m.message.includes('Send the encrypted code'))\r\n );\r\n \r\n if (existingMessages.length === 0) {\r\n setMessages(prev => [...prev, { \r\n message: '\uD83D\uDD10 Secure invitation created and encrypted!', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n setMessages(prev => [...prev, { \r\n message: '\uD83D\uDCE4 Send the invitation code to your interlocutor via a secure channel (voice call, SMS, etc.)..', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n }\r\n \r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } catch (error) {\r\n setMessages(prev => [...prev, { \r\n message: `\u274C Error creating invitation: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n };\r\n \r\n const handleCreateAnswer = async () => {\r\n try {\r\n if (!offerInput.trim()) {\r\n setMessages(prev => [...prev, { \r\n message: '\u26A0\uFE0F You need to insert the invitation code from your interlocutor.', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n return;\r\n }\r\n \r\n try {\r\n setMessages(prev => [...prev, { \r\n message: '\uD83D\uDD04 Processing the secure invitation...', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n setAnswerData('');\r\n setShowAnswerStep(false);\r\n \r\n let offer;\r\n try {\r\n // Parse the offer data directly (no decryption needed with SAS)\r\n offer = JSON.parse(offerInput.trim());\r\n } catch (parseError) {\r\n throw new Error(`Invalid invitation format: ${parseError.message}`);\r\n }\r\n \r\n if (!offer || typeof offer !== 'object') {\r\n throw new Error('The invitation must be an object');\r\n }\r\n \r\n if (!offer.type || offer.type !== 'enhanced_secure_offer') {\r\n throw new Error('Invalid invitation type. Expected enhanced_secure_offer');\r\n }\r\n \r\n console.log('Creating secure answer for offer:', offer);\r\n const answer = await webrtcManagerRef.current.createSecureAnswer(offer);\r\n console.log('Secure answer created:', answer);\r\n \r\n // Store answer data directly (no encryption needed with SAS)\r\n setAnswerData(answer);\r\n setShowAnswerStep(true);\r\n \r\n const existingResponseMessages = messages.filter(m => \r\n m.type === 'system' && \r\n (m.message.includes('Secure response created') || m.message.includes('Send the response'))\r\n );\r\n \r\n if (existingResponseMessages.length === 0) {\r\n setMessages(prev => [...prev, { \r\n message: '\u2705 Secure response created!', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n setMessages(prev => [...prev, { \r\n message: '\uD83D\uDCE4 Send the response code to the initiator via a secure channel..', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n }\r\n \r\n // Update security level after creating answer\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } catch (error) {\r\n console.error('Error in handleCreateAnswer:', error);\r\n setMessages(prev => [...prev, { \r\n message: `\u274C Error processing the invitation: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n } catch (error) {\r\n console.error('Error in handleCreateAnswer:', error);\r\n setMessages(prev => [...prev, { \r\n message: `\u274C Invitation processing error: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n };\r\n \r\n const handleConnect = async () => {\r\n try {\r\n if (!answerInput.trim()) {\r\n setMessages(prev => [...prev, { \r\n message: '\u26A0\uFE0F You need to insert the response code from your interlocutor.', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n return;\r\n }\r\n \r\n try {\r\n setMessages(prev => [...prev, { \r\n message: '\uD83D\uDD04 Processing the secure response...', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n let answer;\r\n try {\r\n // Parse the answer data directly (no decryption needed with SAS)\r\n answer = JSON.parse(answerInput.trim());\r\n } catch (parseError) {\r\n throw new Error(`Invalid response format: ${parseError.message}`);\r\n }\r\n \r\n if (!answer || typeof answer !== 'object') {\r\n throw new Error('The response must be an object');\r\n }\r\n \r\n if (!answer.type || answer.type !== 'enhanced_secure_answer') {\r\n throw new Error('Invalid response type. Expected enhanced\\_secure\\_answer');\r\n }\r\n \r\n await webrtcManagerRef.current.handleSecureAnswer(answer);\r\n \r\n if (sessionManager.canActivateSession() && pendingSession) {\r\n const result = sessionManager.safeActivateSession(pendingSession.type, pendingSession.preimage, pendingSession.paymentHash);\r\n if (result.success) {\r\n setPendingSession(null);\r\n setSessionTimeLeft(sessionManager.getTimeLeft()); \r\n setMessages(prev => [...prev, { \r\n message: `\uD83D\uDCB0 Session activated on ${sessionManager.sessionPrices[pendingSession.type].hours}\u0447 (${result.method})`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n } else {\r\n setMessages(prev => [...prev, { \r\n message: `\u274C Session activation error: ${result.reason}`, \r\n type: 'error',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: '\uD83D\uDD04 Finalizing the secure connection...', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n // Update security level after handling answer\r\n if (!window.isUpdatingSecurity) {\r\n updateSecurityLevel().catch(console.error);\r\n }\r\n } catch (error) {\r\n setMessages(prev => [...prev, { \r\n message: `\u274C Connection setup error: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n if (!error.message.includes('Too old') && !error.message.includes('too old')) {\r\n setPendingSession(null);\r\n }\r\n } \r\n } catch (error) {\r\n setMessages(prev => [...prev, { \r\n message: `\u274C Connection setup error: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n if (!error.message.includes('\u0441Too old') && !error.message.includes('too old')) {\r\n setPendingSession(null);\r\n }\r\n }\r\n };\r\n \r\n const handleVerifyConnection = (isValid) => {\r\n if (isValid) {\r\n webrtcManagerRef.current.confirmVerification();\r\n // Mark local verification as confirmed\r\n setLocalVerificationConfirmed(true);\r\n } else {\r\n setMessages(prev => [...prev, { \r\n message: '\u274C Verification rejected. The connection is unsafe! Session reset..', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n setShowVerification(false);\r\n setVerificationCode('');\r\n \r\n // Reset UI to initial state\r\n setConnectionStatus('disconnected');\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setKeyFingerprint('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n setMessages([]);\r\n \r\n sessionManager.resetSession();\r\n setSessionTimeLeft(0);\r\n setPendingSession(null);\r\n \r\n // Dispatch disconnected event for SessionTimer\r\n document.dispatchEvent(new CustomEvent('disconnected'));\r\n \r\n handleDisconnect();\r\n }\r\n };\r\n \r\n const handleSendMessage = async () => {\r\n if (!messageInput.trim()) {\r\n return;\r\n }\r\n \r\n if (!webrtcManagerRef.current) {\r\n return;\r\n }\r\n \r\n if (!webrtcManagerRef.current.isConnected()) {\r\n return;\r\n }\r\n \r\n try {\r\n \r\n // Add the message to local messages immediately (sent message)\r\n addMessageWithAutoScroll(messageInput.trim(), 'sent');\r\n \r\n // Use sendMessage for simple text messages instead of sendSecureMessage\r\n await webrtcManagerRef.current.sendMessage(messageInput);\r\n setMessageInput('');\r\n } catch (error) {\r\n const msg = String(error?.message || error);\r\n if (!/queued for sending|Data channel not ready/i.test(msg)) {\r\n addMessageWithAutoScroll(`\u274C Sending error: ${msg}`,'system');\r\n }\r\n }\r\n };\r\n \r\n const handleClearData = () => {\r\n // \u041E\u0447\u0438\u0449\u0430\u0435\u043C \u0432\u0441\u0435 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u044F \u0441\u043E\u0435\u0434\u0438\u043D\u0435\u043D\u0438\u044F\r\n setOfferData('');\r\n setAnswerData('');\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setShowVerification(false);\r\n setVerificationCode('');\r\n setIsVerified(false);\r\n setKeyFingerprint('');\r\n setSecurityLevel(null);\r\n setConnectionStatus('disconnected');\r\n setMessages([]);\r\n setMessageInput('');\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // PAKE passwords removed - using SAS verification instead \r\n \r\n // \u041D\u0435 \u043E\u0447\u0438\u0449\u0430\u0435\u043C \u043A\u043E\u043D\u0441\u043E\u043B\u044C \u043F\u0440\u0438 \u043E\u0447\u0438\u0441\u0442\u043A\u0435 \u0434\u0430\u043D\u043D\u044B\u0445\r\n // \u0447\u0442\u043E\u0431\u044B \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C \u043C\u043E\u0433 \u0432\u0438\u0434\u0435\u0442\u044C \u043E\u0448\u0438\u0431\u043A\u0438\r\n // if (typeof console.clear === 'function') {\r\n // console.clear();\r\n // }\r\n \r\n // Cleanup pay-per-session state\r\n if (sessionManager) {\r\n sessionManager.cleanup();\r\n setSessionTimeLeft(0);\r\n }\r\n setShowPaymentModal(false);\r\n \r\n setPendingSession(null);\r\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\r\n setSessionManager(null);\r\n };\r\n \r\n const handleDisconnect = () => {\r\n if (sessionManager && sessionManager.hasActiveSession()) {\r\n sessionManager.resetSession();\r\n setSessionTimeLeft(0);\r\n }\r\n \r\n // Cleanup pay-per-session state\r\n if (sessionManager) {\r\n sessionManager.cleanup();\r\n }\r\n setShowPaymentModal(false);\r\n \r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n \r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n setConnectionStatus('disconnected');\r\n \r\n // Clear verification states\r\n setLocalVerificationConfirmed(false);\r\n setRemoteVerificationConfirmed(false);\r\n setBothVerificationsConfirmed(false);\r\n \r\n // Reset UI to initial state\r\n setConnectionStatus('disconnected');\r\n setShowVerification(false);\r\n setOfferData(null);\r\n setAnswerData(null);\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setKeyFingerprint('');\r\n setVerificationCode('');\r\n setSecurityLevel(null);\r\n setIsVerified(false);\r\n \r\n setMessages([]);\r\n \r\n // \u041D\u0435 \u043E\u0447\u0438\u0449\u0430\u0435\u043C \u043A\u043E\u043D\u0441\u043E\u043B\u044C \u043F\u0440\u0438 \u043E\u0442\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0438\r\n // \u0447\u0442\u043E\u0431\u044B \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C \u043C\u043E\u0433 \u0432\u0438\u0434\u0435\u0442\u044C \u043E\u0448\u0438\u0431\u043A\u0438\r\n // if (typeof console.clear === 'function') {\r\n // console.clear();\r\n // }\r\n \r\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\r\n document.dispatchEvent(new CustomEvent('disconnected'));\r\n \r\n document.dispatchEvent(new CustomEvent('session-cleanup', {\r\n detail: { \r\n timestamp: Date.now(),\r\n reason: 'manual_disconnect'\r\n }\r\n }));\r\n \r\n setTimeout(() => {\r\n if (sessionManager && sessionManager.hasActiveSession()) {\r\n sessionManager.resetSession();\r\n setSessionTimeLeft(0);\r\n }\r\n }, 500);\r\n \r\n handleClearData();\r\n \r\n setTimeout(() => {\r\n setSessionManager(null);\r\n }, 1000);\r\n };\r\n \r\n const handleSessionActivated = (session) => {\r\n let message;\r\n if (session.type === 'demo') {\r\n message = `\uD83C\uDFAE Demo session activated for 6 minutes. You can create invitations!`;\r\n } else {\r\n const hours = sessionManager.sessionPrices[session.type]?.hours || 0;\r\n message = `\uD83D\uDCB0 Session activated for ${hours}h. You can create invitations!`;\r\n }\r\n \r\n addMessageWithAutoScroll(message, 'system');\r\n \r\n };\r\n \r\n React.useEffect(() => {\r\n if (connectionStatus === 'connected' && isVerified) {\r\n addMessageWithAutoScroll('\uD83C\uDF89 Secure connection successfully established and verified! You can now communicate safely with full protection against MITM attacks and Perfect Forward Secrecy..', 'system');\r\n \r\n }\r\n }, [connectionStatus, isVerified]);\r\n \r\n const isConnectedAndVerified = connectionStatus === 'connected' && isVerified;\r\n \r\n React.useEffect(() => {\r\n if (isConnectedAndVerified && sessionManager.canActivateSession() && pendingSession && connectionStatus !== 'failed') {\r\n const result = sessionManager.safeActivateSession(pendingSession.type, pendingSession.preimage, pendingSession.paymentHash);\r\n if (result.success) {\r\n setPendingSession(null);\r\n setSessionTimeLeft(sessionManager.getTimeLeft()); \r\n let message;\r\n if (pendingSession.type === 'demo') {\r\n message = `\uD83C\uDFAE Demo session activated for 6 minutes (${result.method})`;\r\n } else {\r\n const hours = sessionManager.sessionPrices[pendingSession.type]?.hours || 0;\r\n message = `\uD83D\uDCB0 Session activated for ${hours}h (${result.method})`;\r\n }\r\n \r\n addMessageWithAutoScroll(message, 'system');\r\n } else {\r\n addMessageWithAutoScroll(`\u274C Session activation error: ${result.reason}`, 'error');\r\n }\r\n }\r\n }, [isConnectedAndVerified, sessionManager, pendingSession, connectionStatus]);\r\n \r\n return React.createElement('div', { \r\n className: \"minimal-bg min-h-screen\" \r\n }, [\r\n React.createElement(EnhancedMinimalHeader, {\r\n key: 'header',\r\n status: connectionStatus,\r\n fingerprint: keyFingerprint,\r\n verificationCode: verificationCode,\r\n onDisconnect: handleDisconnect,\r\n isConnected: isConnectedAndVerified,\r\n securityLevel: securityLevel,\r\n sessionManager: sessionManager,\r\n sessionTimeLeft: sessionTimeLeft\r\n }),\r\n \r\n React.createElement('main', {\r\n key: 'main'\r\n }, \r\n isConnectedAndVerified\r\n ? React.createElement(EnhancedChatInterface, {\r\n messages: messages,\r\n messageInput: messageInput,\r\n setMessageInput: setMessageInput,\r\n onSendMessage: handleSendMessage,\r\n onDisconnect: handleDisconnect,\r\n keyFingerprint: keyFingerprint,\r\n isVerified: isVerified,\r\n chatMessagesRef: chatMessagesRef,\r\n webrtcManager: webrtcManagerRef.current\r\n })\r\n : React.createElement(EnhancedConnectionSetup, {\r\n onCreateOffer: handleCreateOffer,\r\n onCreateAnswer: handleCreateAnswer,\r\n onConnect: handleConnect,\r\n onClearData: handleClearData,\r\n onVerifyConnection: handleVerifyConnection,\r\n connectionStatus: connectionStatus,\r\n offerData: offerData,\r\n answerData: answerData,\r\n offerInput: offerInput,\r\n setOfferInput: setOfferInput,\r\n answerInput: answerInput,\r\n setAnswerInput: setAnswerInput,\r\n showOfferStep: showOfferStep,\r\n showAnswerStep: showAnswerStep,\r\n verificationCode: verificationCode,\r\n showVerification: showVerification,\r\n messages: messages,\r\n localVerificationConfirmed: localVerificationConfirmed,\r\n remoteVerificationConfirmed: remoteVerificationConfirmed,\r\n bothVerificationsConfirmed: bothVerificationsConfirmed,\r\n // PAKE passwords removed - using SAS verification instead\r\n })\r\n ),\r\n \r\n // PAKE Password Modal removed - using SAS verification instead\r\n \r\n // Payment Modal\r\n React.createElement(PaymentModal, {\r\n key: 'payment-modal',\r\n isOpen: showPaymentModal,\r\n onClose: () => setShowPaymentModal(false),\r\n sessionManager: sessionManager,\r\n onSessionPurchased: (session) => { setPendingSession(session); handleSessionActivated({ type: session.type }); }\r\n })\r\n ]);\r\n };\r\n function initializeApp() {\r\n if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureWebRTCManager) {\r\n ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root'));\r\n } else {\r\n console.error('\u274C \u041C\u043E\u0434\u0443\u043B\u0438 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u044B:', {\r\n hasCrypto: !!window.EnhancedSecureCryptoUtils,\r\n hasWebRTC: !!window.EnhancedSecureWebRTCManager\r\n });\r\n }\r\n }\r\n if (typeof window !== 'undefined' && !window.initializeApp) {\r\n window.initializeApp = initializeApp;\r\n }\r\n // Render Enhanced Application\r\n ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root'));"], + "mappings": "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", + "names": ["scrollToBottom"] +} diff --git a/dist/qr-local.js b/dist/qr-local.js new file mode 100644 index 0000000..1fe1e7b --- /dev/null +++ b/dist/qr-local.js @@ -0,0 +1,2114 @@ +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); + +// node_modules/qrcode/lib/can-promise.js +var require_can_promise = __commonJS({ + "node_modules/qrcode/lib/can-promise.js"(exports, module) { + module.exports = function() { + return typeof Promise === "function" && Promise.prototype && Promise.prototype.then; + }; + } +}); + +// node_modules/qrcode/lib/core/utils.js +var require_utils = __commonJS({ + "node_modules/qrcode/lib/core/utils.js"(exports) { + var toSJISFunction; + var CODEWORDS_COUNT = [ + 0, + // Not used + 26, + 44, + 70, + 100, + 134, + 172, + 196, + 242, + 292, + 346, + 404, + 466, + 532, + 581, + 655, + 733, + 815, + 901, + 991, + 1085, + 1156, + 1258, + 1364, + 1474, + 1588, + 1706, + 1828, + 1921, + 2051, + 2185, + 2323, + 2465, + 2611, + 2761, + 2876, + 3034, + 3196, + 3362, + 3532, + 3706 + ]; + exports.getSymbolSize = function getSymbolSize(version) { + if (!version) throw new Error('"version" cannot be null or undefined'); + if (version < 1 || version > 40) throw new Error('"version" should be in range from 1 to 40'); + return version * 4 + 17; + }; + exports.getSymbolTotalCodewords = function getSymbolTotalCodewords(version) { + return CODEWORDS_COUNT[version]; + }; + exports.getBCHDigit = function(data) { + let digit = 0; + while (data !== 0) { + digit++; + data >>>= 1; + } + return digit; + }; + exports.setToSJISFunction = function setToSJISFunction(f) { + if (typeof f !== "function") { + throw new Error('"toSJISFunc" is not a valid function.'); + } + toSJISFunction = f; + }; + exports.isKanjiModeEnabled = function() { + return typeof toSJISFunction !== "undefined"; + }; + exports.toSJIS = function toSJIS(kanji) { + return toSJISFunction(kanji); + }; + } +}); + +// node_modules/qrcode/lib/core/error-correction-level.js +var require_error_correction_level = __commonJS({ + "node_modules/qrcode/lib/core/error-correction-level.js"(exports) { + exports.L = { bit: 1 }; + exports.M = { bit: 0 }; + exports.Q = { bit: 3 }; + exports.H = { bit: 2 }; + function fromString(string) { + if (typeof string !== "string") { + throw new Error("Param is not a string"); + } + const lcStr = string.toLowerCase(); + switch (lcStr) { + case "l": + case "low": + return exports.L; + case "m": + case "medium": + return exports.M; + case "q": + case "quartile": + return exports.Q; + case "h": + case "high": + return exports.H; + default: + throw new Error("Unknown EC Level: " + string); + } + } + exports.isValid = function isValid(level) { + return level && typeof level.bit !== "undefined" && level.bit >= 0 && level.bit < 4; + }; + exports.from = function from(value, defaultValue) { + if (exports.isValid(value)) { + return value; + } + try { + return fromString(value); + } catch (e) { + return defaultValue; + } + }; + } +}); + +// node_modules/qrcode/lib/core/bit-buffer.js +var require_bit_buffer = __commonJS({ + "node_modules/qrcode/lib/core/bit-buffer.js"(exports, module) { + function BitBuffer() { + this.buffer = []; + this.length = 0; + } + BitBuffer.prototype = { + get: function(index) { + const bufIndex = Math.floor(index / 8); + return (this.buffer[bufIndex] >>> 7 - index % 8 & 1) === 1; + }, + put: function(num, length) { + for (let i = 0; i < length; i++) { + this.putBit((num >>> length - i - 1 & 1) === 1); + } + }, + getLengthInBits: function() { + return this.length; + }, + putBit: function(bit) { + const bufIndex = Math.floor(this.length / 8); + if (this.buffer.length <= bufIndex) { + this.buffer.push(0); + } + if (bit) { + this.buffer[bufIndex] |= 128 >>> this.length % 8; + } + this.length++; + } + }; + module.exports = BitBuffer; + } +}); + +// node_modules/qrcode/lib/core/bit-matrix.js +var require_bit_matrix = __commonJS({ + "node_modules/qrcode/lib/core/bit-matrix.js"(exports, module) { + function BitMatrix(size) { + if (!size || size < 1) { + throw new Error("BitMatrix size must be defined and greater than 0"); + } + this.size = size; + this.data = new Uint8Array(size * size); + this.reservedBit = new Uint8Array(size * size); + } + BitMatrix.prototype.set = function(row, col, value, reserved) { + const index = row * this.size + col; + this.data[index] = value; + if (reserved) this.reservedBit[index] = true; + }; + BitMatrix.prototype.get = function(row, col) { + return this.data[row * this.size + col]; + }; + BitMatrix.prototype.xor = function(row, col, value) { + this.data[row * this.size + col] ^= value; + }; + BitMatrix.prototype.isReserved = function(row, col) { + return this.reservedBit[row * this.size + col]; + }; + module.exports = BitMatrix; + } +}); + +// node_modules/qrcode/lib/core/alignment-pattern.js +var require_alignment_pattern = __commonJS({ + "node_modules/qrcode/lib/core/alignment-pattern.js"(exports) { + var getSymbolSize = require_utils().getSymbolSize; + exports.getRowColCoords = function getRowColCoords(version) { + if (version === 1) return []; + const posCount = Math.floor(version / 7) + 2; + const size = getSymbolSize(version); + const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2; + const positions = [size - 7]; + for (let i = 1; i < posCount - 1; i++) { + positions[i] = positions[i - 1] - intervals; + } + positions.push(6); + return positions.reverse(); + }; + exports.getPositions = function getPositions(version) { + const coords = []; + const pos = exports.getRowColCoords(version); + const posLength = pos.length; + for (let i = 0; i < posLength; i++) { + for (let j = 0; j < posLength; j++) { + if (i === 0 && j === 0 || // top-left + i === 0 && j === posLength - 1 || // bottom-left + i === posLength - 1 && j === 0) { + continue; + } + coords.push([pos[i], pos[j]]); + } + } + return coords; + }; + } +}); + +// node_modules/qrcode/lib/core/finder-pattern.js +var require_finder_pattern = __commonJS({ + "node_modules/qrcode/lib/core/finder-pattern.js"(exports) { + var getSymbolSize = require_utils().getSymbolSize; + var FINDER_PATTERN_SIZE = 7; + exports.getPositions = function getPositions(version) { + const size = getSymbolSize(version); + return [ + // top-left + [0, 0], + // top-right + [size - FINDER_PATTERN_SIZE, 0], + // bottom-left + [0, size - FINDER_PATTERN_SIZE] + ]; + }; + } +}); + +// node_modules/qrcode/lib/core/mask-pattern.js +var require_mask_pattern = __commonJS({ + "node_modules/qrcode/lib/core/mask-pattern.js"(exports) { + exports.Patterns = { + PATTERN000: 0, + PATTERN001: 1, + PATTERN010: 2, + PATTERN011: 3, + PATTERN100: 4, + PATTERN101: 5, + PATTERN110: 6, + PATTERN111: 7 + }; + var PenaltyScores = { + N1: 3, + N2: 3, + N3: 40, + N4: 10 + }; + exports.isValid = function isValid(mask) { + return mask != null && mask !== "" && !isNaN(mask) && mask >= 0 && mask <= 7; + }; + exports.from = function from(value) { + return exports.isValid(value) ? parseInt(value, 10) : void 0; + }; + exports.getPenaltyN1 = function getPenaltyN1(data) { + const size = data.size; + let points = 0; + let sameCountCol = 0; + let sameCountRow = 0; + let lastCol = null; + let lastRow = null; + for (let row = 0; row < size; row++) { + sameCountCol = sameCountRow = 0; + lastCol = lastRow = null; + for (let col = 0; col < size; col++) { + let module2 = data.get(row, col); + if (module2 === lastCol) { + sameCountCol++; + } else { + if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5); + lastCol = module2; + sameCountCol = 1; + } + module2 = data.get(col, row); + if (module2 === lastRow) { + sameCountRow++; + } else { + if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5); + lastRow = module2; + sameCountRow = 1; + } + } + if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5); + if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5); + } + return points; + }; + exports.getPenaltyN2 = function getPenaltyN2(data) { + const size = data.size; + let points = 0; + for (let row = 0; row < size - 1; row++) { + for (let col = 0; col < size - 1; col++) { + const last = data.get(row, col) + data.get(row, col + 1) + data.get(row + 1, col) + data.get(row + 1, col + 1); + if (last === 4 || last === 0) points++; + } + } + return points * PenaltyScores.N2; + }; + exports.getPenaltyN3 = function getPenaltyN3(data) { + const size = data.size; + let points = 0; + let bitsCol = 0; + let bitsRow = 0; + for (let row = 0; row < size; row++) { + bitsCol = bitsRow = 0; + for (let col = 0; col < size; col++) { + bitsCol = bitsCol << 1 & 2047 | data.get(row, col); + if (col >= 10 && (bitsCol === 1488 || bitsCol === 93)) points++; + bitsRow = bitsRow << 1 & 2047 | data.get(col, row); + if (col >= 10 && (bitsRow === 1488 || bitsRow === 93)) points++; + } + } + return points * PenaltyScores.N3; + }; + exports.getPenaltyN4 = function getPenaltyN4(data) { + let darkCount = 0; + const modulesCount = data.data.length; + for (let i = 0; i < modulesCount; i++) darkCount += data.data[i]; + const k = Math.abs(Math.ceil(darkCount * 100 / modulesCount / 5) - 10); + return k * PenaltyScores.N4; + }; + function getMaskAt(maskPattern, i, j) { + switch (maskPattern) { + case exports.Patterns.PATTERN000: + return (i + j) % 2 === 0; + case exports.Patterns.PATTERN001: + return i % 2 === 0; + case exports.Patterns.PATTERN010: + return j % 3 === 0; + case exports.Patterns.PATTERN011: + return (i + j) % 3 === 0; + case exports.Patterns.PATTERN100: + return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0; + case exports.Patterns.PATTERN101: + return i * j % 2 + i * j % 3 === 0; + case exports.Patterns.PATTERN110: + return (i * j % 2 + i * j % 3) % 2 === 0; + case exports.Patterns.PATTERN111: + return (i * j % 3 + (i + j) % 2) % 2 === 0; + default: + throw new Error("bad maskPattern:" + maskPattern); + } + } + exports.applyMask = function applyMask(pattern, data) { + const size = data.size; + for (let col = 0; col < size; col++) { + for (let row = 0; row < size; row++) { + if (data.isReserved(row, col)) continue; + data.xor(row, col, getMaskAt(pattern, row, col)); + } + } + }; + exports.getBestMask = function getBestMask(data, setupFormatFunc) { + const numPatterns = Object.keys(exports.Patterns).length; + let bestPattern = 0; + let lowerPenalty = Infinity; + for (let p = 0; p < numPatterns; p++) { + setupFormatFunc(p); + exports.applyMask(p, data); + const penalty = exports.getPenaltyN1(data) + exports.getPenaltyN2(data) + exports.getPenaltyN3(data) + exports.getPenaltyN4(data); + exports.applyMask(p, data); + if (penalty < lowerPenalty) { + lowerPenalty = penalty; + bestPattern = p; + } + } + return bestPattern; + }; + } +}); + +// node_modules/qrcode/lib/core/error-correction-code.js +var require_error_correction_code = __commonJS({ + "node_modules/qrcode/lib/core/error-correction-code.js"(exports) { + var ECLevel = require_error_correction_level(); + var EC_BLOCKS_TABLE = [ + // L M Q H + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 1, + 2, + 2, + 4, + 1, + 2, + 4, + 4, + 2, + 4, + 4, + 4, + 2, + 4, + 6, + 5, + 2, + 4, + 6, + 6, + 2, + 5, + 8, + 8, + 4, + 5, + 8, + 8, + 4, + 5, + 8, + 11, + 4, + 8, + 10, + 11, + 4, + 9, + 12, + 16, + 4, + 9, + 16, + 16, + 6, + 10, + 12, + 18, + 6, + 10, + 17, + 16, + 6, + 11, + 16, + 19, + 6, + 13, + 18, + 21, + 7, + 14, + 21, + 25, + 8, + 16, + 20, + 25, + 8, + 17, + 23, + 25, + 9, + 17, + 23, + 34, + 9, + 18, + 25, + 30, + 10, + 20, + 27, + 32, + 12, + 21, + 29, + 35, + 12, + 23, + 34, + 37, + 12, + 25, + 34, + 40, + 13, + 26, + 35, + 42, + 14, + 28, + 38, + 45, + 15, + 29, + 40, + 48, + 16, + 31, + 43, + 51, + 17, + 33, + 45, + 54, + 18, + 35, + 48, + 57, + 19, + 37, + 51, + 60, + 19, + 38, + 53, + 63, + 20, + 40, + 56, + 66, + 21, + 43, + 59, + 70, + 22, + 45, + 62, + 74, + 24, + 47, + 65, + 77, + 25, + 49, + 68, + 81 + ]; + var EC_CODEWORDS_TABLE = [ + // L M Q H + 7, + 10, + 13, + 17, + 10, + 16, + 22, + 28, + 15, + 26, + 36, + 44, + 20, + 36, + 52, + 64, + 26, + 48, + 72, + 88, + 36, + 64, + 96, + 112, + 40, + 72, + 108, + 130, + 48, + 88, + 132, + 156, + 60, + 110, + 160, + 192, + 72, + 130, + 192, + 224, + 80, + 150, + 224, + 264, + 96, + 176, + 260, + 308, + 104, + 198, + 288, + 352, + 120, + 216, + 320, + 384, + 132, + 240, + 360, + 432, + 144, + 280, + 408, + 480, + 168, + 308, + 448, + 532, + 180, + 338, + 504, + 588, + 196, + 364, + 546, + 650, + 224, + 416, + 600, + 700, + 224, + 442, + 644, + 750, + 252, + 476, + 690, + 816, + 270, + 504, + 750, + 900, + 300, + 560, + 810, + 960, + 312, + 588, + 870, + 1050, + 336, + 644, + 952, + 1110, + 360, + 700, + 1020, + 1200, + 390, + 728, + 1050, + 1260, + 420, + 784, + 1140, + 1350, + 450, + 812, + 1200, + 1440, + 480, + 868, + 1290, + 1530, + 510, + 924, + 1350, + 1620, + 540, + 980, + 1440, + 1710, + 570, + 1036, + 1530, + 1800, + 570, + 1064, + 1590, + 1890, + 600, + 1120, + 1680, + 1980, + 630, + 1204, + 1770, + 2100, + 660, + 1260, + 1860, + 2220, + 720, + 1316, + 1950, + 2310, + 750, + 1372, + 2040, + 2430 + ]; + exports.getBlocksCount = function getBlocksCount(version, errorCorrectionLevel) { + switch (errorCorrectionLevel) { + case ECLevel.L: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 0]; + case ECLevel.M: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 1]; + case ECLevel.Q: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 2]; + case ECLevel.H: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 3]; + default: + return void 0; + } + }; + exports.getTotalCodewordsCount = function getTotalCodewordsCount(version, errorCorrectionLevel) { + switch (errorCorrectionLevel) { + case ECLevel.L: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0]; + case ECLevel.M: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1]; + case ECLevel.Q: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2]; + case ECLevel.H: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3]; + default: + return void 0; + } + }; + } +}); + +// node_modules/qrcode/lib/core/galois-field.js +var require_galois_field = __commonJS({ + "node_modules/qrcode/lib/core/galois-field.js"(exports) { + var EXP_TABLE = new Uint8Array(512); + var LOG_TABLE = new Uint8Array(256); + (function initTables() { + let x = 1; + for (let i = 0; i < 255; i++) { + EXP_TABLE[i] = x; + LOG_TABLE[x] = i; + x <<= 1; + if (x & 256) { + x ^= 285; + } + } + for (let i = 255; i < 512; i++) { + EXP_TABLE[i] = EXP_TABLE[i - 255]; + } + })(); + exports.log = function log(n) { + if (n < 1) throw new Error("log(" + n + ")"); + return LOG_TABLE[n]; + }; + exports.exp = function exp(n) { + return EXP_TABLE[n]; + }; + exports.mul = function mul(x, y) { + if (x === 0 || y === 0) return 0; + return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]]; + }; + } +}); + +// node_modules/qrcode/lib/core/polynomial.js +var require_polynomial = __commonJS({ + "node_modules/qrcode/lib/core/polynomial.js"(exports) { + var GF = require_galois_field(); + exports.mul = function mul(p1, p2) { + const coeff = new Uint8Array(p1.length + p2.length - 1); + for (let i = 0; i < p1.length; i++) { + for (let j = 0; j < p2.length; j++) { + coeff[i + j] ^= GF.mul(p1[i], p2[j]); + } + } + return coeff; + }; + exports.mod = function mod(divident, divisor) { + let result = new Uint8Array(divident); + while (result.length - divisor.length >= 0) { + const coeff = result[0]; + for (let i = 0; i < divisor.length; i++) { + result[i] ^= GF.mul(divisor[i], coeff); + } + let offset = 0; + while (offset < result.length && result[offset] === 0) offset++; + result = result.slice(offset); + } + return result; + }; + exports.generateECPolynomial = function generateECPolynomial(degree) { + let poly = new Uint8Array([1]); + for (let i = 0; i < degree; i++) { + poly = exports.mul(poly, new Uint8Array([1, GF.exp(i)])); + } + return poly; + }; + } +}); + +// node_modules/qrcode/lib/core/reed-solomon-encoder.js +var require_reed_solomon_encoder = __commonJS({ + "node_modules/qrcode/lib/core/reed-solomon-encoder.js"(exports, module) { + var Polynomial = require_polynomial(); + function ReedSolomonEncoder(degree) { + this.genPoly = void 0; + this.degree = degree; + if (this.degree) this.initialize(this.degree); + } + ReedSolomonEncoder.prototype.initialize = function initialize(degree) { + this.degree = degree; + this.genPoly = Polynomial.generateECPolynomial(this.degree); + }; + ReedSolomonEncoder.prototype.encode = function encode(data) { + if (!this.genPoly) { + throw new Error("Encoder not initialized"); + } + const paddedData = new Uint8Array(data.length + this.degree); + paddedData.set(data); + const remainder = Polynomial.mod(paddedData, this.genPoly); + const start = this.degree - remainder.length; + if (start > 0) { + const buff = new Uint8Array(this.degree); + buff.set(remainder, start); + return buff; + } + return remainder; + }; + module.exports = ReedSolomonEncoder; + } +}); + +// node_modules/qrcode/lib/core/version-check.js +var require_version_check = __commonJS({ + "node_modules/qrcode/lib/core/version-check.js"(exports) { + exports.isValid = function isValid(version) { + return !isNaN(version) && version >= 1 && version <= 40; + }; + } +}); + +// node_modules/qrcode/lib/core/regex.js +var require_regex = __commonJS({ + "node_modules/qrcode/lib/core/regex.js"(exports) { + var numeric = "[0-9]+"; + var alphanumeric = "[A-Z $%*+\\-./:]+"; + var kanji = "(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+"; + kanji = kanji.replace(/u/g, "\\u"); + var byte = "(?:(?![A-Z0-9 $%*+\\-./:]|" + kanji + ")(?:.|[\r\n]))+"; + exports.KANJI = new RegExp(kanji, "g"); + exports.BYTE_KANJI = new RegExp("[^A-Z0-9 $%*+\\-./:]+", "g"); + exports.BYTE = new RegExp(byte, "g"); + exports.NUMERIC = new RegExp(numeric, "g"); + exports.ALPHANUMERIC = new RegExp(alphanumeric, "g"); + var TEST_KANJI = new RegExp("^" + kanji + "$"); + var TEST_NUMERIC = new RegExp("^" + numeric + "$"); + var TEST_ALPHANUMERIC = new RegExp("^[A-Z0-9 $%*+\\-./:]+$"); + exports.testKanji = function testKanji(str) { + return TEST_KANJI.test(str); + }; + exports.testNumeric = function testNumeric(str) { + return TEST_NUMERIC.test(str); + }; + exports.testAlphanumeric = function testAlphanumeric(str) { + return TEST_ALPHANUMERIC.test(str); + }; + } +}); + +// node_modules/qrcode/lib/core/mode.js +var require_mode = __commonJS({ + "node_modules/qrcode/lib/core/mode.js"(exports) { + var VersionCheck = require_version_check(); + var Regex = require_regex(); + exports.NUMERIC = { + id: "Numeric", + bit: 1 << 0, + ccBits: [10, 12, 14] + }; + exports.ALPHANUMERIC = { + id: "Alphanumeric", + bit: 1 << 1, + ccBits: [9, 11, 13] + }; + exports.BYTE = { + id: "Byte", + bit: 1 << 2, + ccBits: [8, 16, 16] + }; + exports.KANJI = { + id: "Kanji", + bit: 1 << 3, + ccBits: [8, 10, 12] + }; + exports.MIXED = { + bit: -1 + }; + exports.getCharCountIndicator = function getCharCountIndicator(mode, version) { + if (!mode.ccBits) throw new Error("Invalid mode: " + mode); + if (!VersionCheck.isValid(version)) { + throw new Error("Invalid version: " + version); + } + if (version >= 1 && version < 10) return mode.ccBits[0]; + else if (version < 27) return mode.ccBits[1]; + return mode.ccBits[2]; + }; + exports.getBestModeForData = function getBestModeForData(dataStr) { + if (Regex.testNumeric(dataStr)) return exports.NUMERIC; + else if (Regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC; + else if (Regex.testKanji(dataStr)) return exports.KANJI; + else return exports.BYTE; + }; + exports.toString = function toString(mode) { + if (mode && mode.id) return mode.id; + throw new Error("Invalid mode"); + }; + exports.isValid = function isValid(mode) { + return mode && mode.bit && mode.ccBits; + }; + function fromString(string) { + if (typeof string !== "string") { + throw new Error("Param is not a string"); + } + const lcStr = string.toLowerCase(); + switch (lcStr) { + case "numeric": + return exports.NUMERIC; + case "alphanumeric": + return exports.ALPHANUMERIC; + case "kanji": + return exports.KANJI; + case "byte": + return exports.BYTE; + default: + throw new Error("Unknown mode: " + string); + } + } + exports.from = function from(value, defaultValue) { + if (exports.isValid(value)) { + return value; + } + try { + return fromString(value); + } catch (e) { + return defaultValue; + } + }; + } +}); + +// node_modules/qrcode/lib/core/version.js +var require_version = __commonJS({ + "node_modules/qrcode/lib/core/version.js"(exports) { + var Utils = require_utils(); + var ECCode = require_error_correction_code(); + var ECLevel = require_error_correction_level(); + var Mode = require_mode(); + var VersionCheck = require_version_check(); + var G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0; + var G18_BCH = Utils.getBCHDigit(G18); + function getBestVersionForDataLength(mode, length, errorCorrectionLevel) { + for (let currentVersion = 1; currentVersion <= 40; currentVersion++) { + if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) { + return currentVersion; + } + } + return void 0; + } + function getReservedBitsCount(mode, version) { + return Mode.getCharCountIndicator(mode, version) + 4; + } + function getTotalBitsFromDataArray(segments, version) { + let totalBits = 0; + segments.forEach(function(data) { + const reservedBits = getReservedBitsCount(data.mode, version); + totalBits += reservedBits + data.getBitsLength(); + }); + return totalBits; + } + function getBestVersionForMixedData(segments, errorCorrectionLevel) { + for (let currentVersion = 1; currentVersion <= 40; currentVersion++) { + const length = getTotalBitsFromDataArray(segments, currentVersion); + if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, Mode.MIXED)) { + return currentVersion; + } + } + return void 0; + } + exports.from = function from(value, defaultValue) { + if (VersionCheck.isValid(value)) { + return parseInt(value, 10); + } + return defaultValue; + }; + exports.getCapacity = function getCapacity(version, errorCorrectionLevel, mode) { + if (!VersionCheck.isValid(version)) { + throw new Error("Invalid QR Code version"); + } + if (typeof mode === "undefined") mode = Mode.BYTE; + const totalCodewords = Utils.getSymbolTotalCodewords(version); + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel); + const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8; + if (mode === Mode.MIXED) return dataTotalCodewordsBits; + const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode, version); + switch (mode) { + case Mode.NUMERIC: + return Math.floor(usableBits / 10 * 3); + case Mode.ALPHANUMERIC: + return Math.floor(usableBits / 11 * 2); + case Mode.KANJI: + return Math.floor(usableBits / 13); + case Mode.BYTE: + default: + return Math.floor(usableBits / 8); + } + }; + exports.getBestVersionForData = function getBestVersionForData(data, errorCorrectionLevel) { + let seg; + const ecl = ECLevel.from(errorCorrectionLevel, ECLevel.M); + if (Array.isArray(data)) { + if (data.length > 1) { + return getBestVersionForMixedData(data, ecl); + } + if (data.length === 0) { + return 1; + } + seg = data[0]; + } else { + seg = data; + } + return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl); + }; + exports.getEncodedBits = function getEncodedBits(version) { + if (!VersionCheck.isValid(version) || version < 7) { + throw new Error("Invalid QR Code version"); + } + let d = version << 12; + while (Utils.getBCHDigit(d) - G18_BCH >= 0) { + d ^= G18 << Utils.getBCHDigit(d) - G18_BCH; + } + return version << 12 | d; + }; + } +}); + +// node_modules/qrcode/lib/core/format-info.js +var require_format_info = __commonJS({ + "node_modules/qrcode/lib/core/format-info.js"(exports) { + var Utils = require_utils(); + var G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0; + var G15_MASK = 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1; + var G15_BCH = Utils.getBCHDigit(G15); + exports.getEncodedBits = function getEncodedBits(errorCorrectionLevel, mask) { + const data = errorCorrectionLevel.bit << 3 | mask; + let d = data << 10; + while (Utils.getBCHDigit(d) - G15_BCH >= 0) { + d ^= G15 << Utils.getBCHDigit(d) - G15_BCH; + } + return (data << 10 | d) ^ G15_MASK; + }; + } +}); + +// node_modules/qrcode/lib/core/numeric-data.js +var require_numeric_data = __commonJS({ + "node_modules/qrcode/lib/core/numeric-data.js"(exports, module) { + var Mode = require_mode(); + function NumericData(data) { + this.mode = Mode.NUMERIC; + this.data = data.toString(); + } + NumericData.getBitsLength = function getBitsLength(length) { + return 10 * Math.floor(length / 3) + (length % 3 ? length % 3 * 3 + 1 : 0); + }; + NumericData.prototype.getLength = function getLength() { + return this.data.length; + }; + NumericData.prototype.getBitsLength = function getBitsLength() { + return NumericData.getBitsLength(this.data.length); + }; + NumericData.prototype.write = function write(bitBuffer) { + let i, group, value; + for (i = 0; i + 3 <= this.data.length; i += 3) { + group = this.data.substr(i, 3); + value = parseInt(group, 10); + bitBuffer.put(value, 10); + } + const remainingNum = this.data.length - i; + if (remainingNum > 0) { + group = this.data.substr(i); + value = parseInt(group, 10); + bitBuffer.put(value, remainingNum * 3 + 1); + } + }; + module.exports = NumericData; + } +}); + +// node_modules/qrcode/lib/core/alphanumeric-data.js +var require_alphanumeric_data = __commonJS({ + "node_modules/qrcode/lib/core/alphanumeric-data.js"(exports, module) { + var Mode = require_mode(); + var ALPHA_NUM_CHARS = [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + " ", + "$", + "%", + "*", + "+", + "-", + ".", + "/", + ":" + ]; + function AlphanumericData(data) { + this.mode = Mode.ALPHANUMERIC; + this.data = data; + } + AlphanumericData.getBitsLength = function getBitsLength(length) { + return 11 * Math.floor(length / 2) + 6 * (length % 2); + }; + AlphanumericData.prototype.getLength = function getLength() { + return this.data.length; + }; + AlphanumericData.prototype.getBitsLength = function getBitsLength() { + return AlphanumericData.getBitsLength(this.data.length); + }; + AlphanumericData.prototype.write = function write(bitBuffer) { + let i; + for (i = 0; i + 2 <= this.data.length; i += 2) { + let value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45; + value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1]); + bitBuffer.put(value, 11); + } + if (this.data.length % 2) { + bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6); + } + }; + module.exports = AlphanumericData; + } +}); + +// node_modules/qrcode/lib/core/byte-data.js +var require_byte_data = __commonJS({ + "node_modules/qrcode/lib/core/byte-data.js"(exports, module) { + var Mode = require_mode(); + function ByteData(data) { + this.mode = Mode.BYTE; + if (typeof data === "string") { + this.data = new TextEncoder().encode(data); + } else { + this.data = new Uint8Array(data); + } + } + ByteData.getBitsLength = function getBitsLength(length) { + return length * 8; + }; + ByteData.prototype.getLength = function getLength() { + return this.data.length; + }; + ByteData.prototype.getBitsLength = function getBitsLength() { + return ByteData.getBitsLength(this.data.length); + }; + ByteData.prototype.write = function(bitBuffer) { + for (let i = 0, l = this.data.length; i < l; i++) { + bitBuffer.put(this.data[i], 8); + } + }; + module.exports = ByteData; + } +}); + +// node_modules/qrcode/lib/core/kanji-data.js +var require_kanji_data = __commonJS({ + "node_modules/qrcode/lib/core/kanji-data.js"(exports, module) { + var Mode = require_mode(); + var Utils = require_utils(); + function KanjiData(data) { + this.mode = Mode.KANJI; + this.data = data; + } + KanjiData.getBitsLength = function getBitsLength(length) { + return length * 13; + }; + KanjiData.prototype.getLength = function getLength() { + return this.data.length; + }; + KanjiData.prototype.getBitsLength = function getBitsLength() { + return KanjiData.getBitsLength(this.data.length); + }; + KanjiData.prototype.write = function(bitBuffer) { + let i; + for (i = 0; i < this.data.length; i++) { + let value = Utils.toSJIS(this.data[i]); + if (value >= 33088 && value <= 40956) { + value -= 33088; + } else if (value >= 57408 && value <= 60351) { + value -= 49472; + } else { + throw new Error( + "Invalid SJIS character: " + this.data[i] + "\nMake sure your charset is UTF-8" + ); + } + value = (value >>> 8 & 255) * 192 + (value & 255); + bitBuffer.put(value, 13); + } + }; + module.exports = KanjiData; + } +}); + +// node_modules/dijkstrajs/dijkstra.js +var require_dijkstra = __commonJS({ + "node_modules/dijkstrajs/dijkstra.js"(exports, module) { + "use strict"; + var dijkstra = { + single_source_shortest_paths: function(graph, s, d) { + var predecessors = {}; + var costs = {}; + costs[s] = 0; + var open = dijkstra.PriorityQueue.make(); + open.push(s, 0); + var closest, u, v, cost_of_s_to_u, adjacent_nodes, cost_of_e, cost_of_s_to_u_plus_cost_of_e, cost_of_s_to_v, first_visit; + while (!open.empty()) { + closest = open.pop(); + u = closest.value; + cost_of_s_to_u = closest.cost; + adjacent_nodes = graph[u] || {}; + for (v in adjacent_nodes) { + if (adjacent_nodes.hasOwnProperty(v)) { + cost_of_e = adjacent_nodes[v]; + cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e; + cost_of_s_to_v = costs[v]; + first_visit = typeof costs[v] === "undefined"; + if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) { + costs[v] = cost_of_s_to_u_plus_cost_of_e; + open.push(v, cost_of_s_to_u_plus_cost_of_e); + predecessors[v] = u; + } + } + } + } + if (typeof d !== "undefined" && typeof costs[d] === "undefined") { + var msg = ["Could not find a path from ", s, " to ", d, "."].join(""); + throw new Error(msg); + } + return predecessors; + }, + extract_shortest_path_from_predecessor_list: function(predecessors, d) { + var nodes = []; + var u = d; + var predecessor; + while (u) { + nodes.push(u); + predecessor = predecessors[u]; + u = predecessors[u]; + } + nodes.reverse(); + return nodes; + }, + find_path: function(graph, s, d) { + var predecessors = dijkstra.single_source_shortest_paths(graph, s, d); + return dijkstra.extract_shortest_path_from_predecessor_list( + predecessors, + d + ); + }, + /** + * A very naive priority queue implementation. + */ + PriorityQueue: { + make: function(opts) { + var T = dijkstra.PriorityQueue, t = {}, key; + opts = opts || {}; + for (key in T) { + if (T.hasOwnProperty(key)) { + t[key] = T[key]; + } + } + t.queue = []; + t.sorter = opts.sorter || T.default_sorter; + return t; + }, + default_sorter: function(a, b) { + return a.cost - b.cost; + }, + /** + * Add a new item to the queue and ensure the highest priority element + * is at the front of the queue. + */ + push: function(value, cost) { + var item = { value, cost }; + this.queue.push(item); + this.queue.sort(this.sorter); + }, + /** + * Return the highest priority element in the queue. + */ + pop: function() { + return this.queue.shift(); + }, + empty: function() { + return this.queue.length === 0; + } + } + }; + if (typeof module !== "undefined") { + module.exports = dijkstra; + } + } +}); + +// node_modules/qrcode/lib/core/segments.js +var require_segments = __commonJS({ + "node_modules/qrcode/lib/core/segments.js"(exports) { + var Mode = require_mode(); + var NumericData = require_numeric_data(); + var AlphanumericData = require_alphanumeric_data(); + var ByteData = require_byte_data(); + var KanjiData = require_kanji_data(); + var Regex = require_regex(); + var Utils = require_utils(); + var dijkstra = require_dijkstra(); + function getStringByteLength(str) { + return unescape(encodeURIComponent(str)).length; + } + function getSegments(regex, mode, str) { + const segments = []; + let result; + while ((result = regex.exec(str)) !== null) { + segments.push({ + data: result[0], + index: result.index, + mode, + length: result[0].length + }); + } + return segments; + } + function getSegmentsFromString(dataStr) { + const numSegs = getSegments(Regex.NUMERIC, Mode.NUMERIC, dataStr); + const alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode.ALPHANUMERIC, dataStr); + let byteSegs; + let kanjiSegs; + if (Utils.isKanjiModeEnabled()) { + byteSegs = getSegments(Regex.BYTE, Mode.BYTE, dataStr); + kanjiSegs = getSegments(Regex.KANJI, Mode.KANJI, dataStr); + } else { + byteSegs = getSegments(Regex.BYTE_KANJI, Mode.BYTE, dataStr); + kanjiSegs = []; + } + const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs); + return segs.sort(function(s1, s2) { + return s1.index - s2.index; + }).map(function(obj) { + return { + data: obj.data, + mode: obj.mode, + length: obj.length + }; + }); + } + function getSegmentBitsLength(length, mode) { + switch (mode) { + case Mode.NUMERIC: + return NumericData.getBitsLength(length); + case Mode.ALPHANUMERIC: + return AlphanumericData.getBitsLength(length); + case Mode.KANJI: + return KanjiData.getBitsLength(length); + case Mode.BYTE: + return ByteData.getBitsLength(length); + } + } + function mergeSegments(segs) { + return segs.reduce(function(acc, curr) { + const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null; + if (prevSeg && prevSeg.mode === curr.mode) { + acc[acc.length - 1].data += curr.data; + return acc; + } + acc.push(curr); + return acc; + }, []); + } + function buildNodes(segs) { + const nodes = []; + for (let i = 0; i < segs.length; i++) { + const seg = segs[i]; + switch (seg.mode) { + case Mode.NUMERIC: + nodes.push([ + seg, + { data: seg.data, mode: Mode.ALPHANUMERIC, length: seg.length }, + { data: seg.data, mode: Mode.BYTE, length: seg.length } + ]); + break; + case Mode.ALPHANUMERIC: + nodes.push([ + seg, + { data: seg.data, mode: Mode.BYTE, length: seg.length } + ]); + break; + case Mode.KANJI: + nodes.push([ + seg, + { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) } + ]); + break; + case Mode.BYTE: + nodes.push([ + { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) } + ]); + } + } + return nodes; + } + function buildGraph(nodes, version) { + const table = {}; + const graph = { start: {} }; + let prevNodeIds = ["start"]; + for (let i = 0; i < nodes.length; i++) { + const nodeGroup = nodes[i]; + const currentNodeIds = []; + for (let j = 0; j < nodeGroup.length; j++) { + const node = nodeGroup[j]; + const key = "" + i + j; + currentNodeIds.push(key); + table[key] = { node, lastCount: 0 }; + graph[key] = {}; + for (let n = 0; n < prevNodeIds.length; n++) { + const prevNodeId = prevNodeIds[n]; + if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) { + graph[prevNodeId][key] = getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) - getSegmentBitsLength(table[prevNodeId].lastCount, node.mode); + table[prevNodeId].lastCount += node.length; + } else { + if (table[prevNodeId]) table[prevNodeId].lastCount = node.length; + graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) + 4 + Mode.getCharCountIndicator(node.mode, version); + } + } + } + prevNodeIds = currentNodeIds; + } + for (let n = 0; n < prevNodeIds.length; n++) { + graph[prevNodeIds[n]].end = 0; + } + return { map: graph, table }; + } + function buildSingleSegment(data, modesHint) { + let mode; + const bestMode = Mode.getBestModeForData(data); + mode = Mode.from(modesHint, bestMode); + if (mode !== Mode.BYTE && mode.bit < bestMode.bit) { + throw new Error('"' + data + '" cannot be encoded with mode ' + Mode.toString(mode) + ".\n Suggested mode is: " + Mode.toString(bestMode)); + } + if (mode === Mode.KANJI && !Utils.isKanjiModeEnabled()) { + mode = Mode.BYTE; + } + switch (mode) { + case Mode.NUMERIC: + return new NumericData(data); + case Mode.ALPHANUMERIC: + return new AlphanumericData(data); + case Mode.KANJI: + return new KanjiData(data); + case Mode.BYTE: + return new ByteData(data); + } + } + exports.fromArray = function fromArray(array) { + return array.reduce(function(acc, seg) { + if (typeof seg === "string") { + acc.push(buildSingleSegment(seg, null)); + } else if (seg.data) { + acc.push(buildSingleSegment(seg.data, seg.mode)); + } + return acc; + }, []); + }; + exports.fromString = function fromString(data, version) { + const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled()); + const nodes = buildNodes(segs); + const graph = buildGraph(nodes, version); + const path = dijkstra.find_path(graph.map, "start", "end"); + const optimizedSegs = []; + for (let i = 1; i < path.length - 1; i++) { + optimizedSegs.push(graph.table[path[i]].node); + } + return exports.fromArray(mergeSegments(optimizedSegs)); + }; + exports.rawSplit = function rawSplit(data) { + return exports.fromArray( + getSegmentsFromString(data, Utils.isKanjiModeEnabled()) + ); + }; + } +}); + +// node_modules/qrcode/lib/core/qrcode.js +var require_qrcode = __commonJS({ + "node_modules/qrcode/lib/core/qrcode.js"(exports) { + var Utils = require_utils(); + var ECLevel = require_error_correction_level(); + var BitBuffer = require_bit_buffer(); + var BitMatrix = require_bit_matrix(); + var AlignmentPattern = require_alignment_pattern(); + var FinderPattern = require_finder_pattern(); + var MaskPattern = require_mask_pattern(); + var ECCode = require_error_correction_code(); + var ReedSolomonEncoder = require_reed_solomon_encoder(); + var Version = require_version(); + var FormatInfo = require_format_info(); + var Mode = require_mode(); + var Segments = require_segments(); + function setupFinderPattern(matrix, version) { + const size = matrix.size; + const pos = FinderPattern.getPositions(version); + for (let i = 0; i < pos.length; i++) { + const row = pos[i][0]; + const col = pos[i][1]; + for (let r = -1; r <= 7; r++) { + if (row + r <= -1 || size <= row + r) continue; + for (let c = -1; c <= 7; c++) { + if (col + c <= -1 || size <= col + c) continue; + if (r >= 0 && r <= 6 && (c === 0 || c === 6) || c >= 0 && c <= 6 && (r === 0 || r === 6) || r >= 2 && r <= 4 && c >= 2 && c <= 4) { + matrix.set(row + r, col + c, true, true); + } else { + matrix.set(row + r, col + c, false, true); + } + } + } + } + } + function setupTimingPattern(matrix) { + const size = matrix.size; + for (let r = 8; r < size - 8; r++) { + const value = r % 2 === 0; + matrix.set(r, 6, value, true); + matrix.set(6, r, value, true); + } + } + function setupAlignmentPattern(matrix, version) { + const pos = AlignmentPattern.getPositions(version); + for (let i = 0; i < pos.length; i++) { + const row = pos[i][0]; + const col = pos[i][1]; + for (let r = -2; r <= 2; r++) { + for (let c = -2; c <= 2; c++) { + if (r === -2 || r === 2 || c === -2 || c === 2 || r === 0 && c === 0) { + matrix.set(row + r, col + c, true, true); + } else { + matrix.set(row + r, col + c, false, true); + } + } + } + } + } + function setupVersionInfo(matrix, version) { + const size = matrix.size; + const bits = Version.getEncodedBits(version); + let row, col, mod; + for (let i = 0; i < 18; i++) { + row = Math.floor(i / 3); + col = i % 3 + size - 8 - 3; + mod = (bits >> i & 1) === 1; + matrix.set(row, col, mod, true); + matrix.set(col, row, mod, true); + } + } + function setupFormatInfo(matrix, errorCorrectionLevel, maskPattern) { + const size = matrix.size; + const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern); + let i, mod; + for (i = 0; i < 15; i++) { + mod = (bits >> i & 1) === 1; + if (i < 6) { + matrix.set(i, 8, mod, true); + } else if (i < 8) { + matrix.set(i + 1, 8, mod, true); + } else { + matrix.set(size - 15 + i, 8, mod, true); + } + if (i < 8) { + matrix.set(8, size - i - 1, mod, true); + } else if (i < 9) { + matrix.set(8, 15 - i - 1 + 1, mod, true); + } else { + matrix.set(8, 15 - i - 1, mod, true); + } + } + matrix.set(size - 8, 8, 1, true); + } + function setupData(matrix, data) { + const size = matrix.size; + let inc = -1; + let row = size - 1; + let bitIndex = 7; + let byteIndex = 0; + for (let col = size - 1; col > 0; col -= 2) { + if (col === 6) col--; + while (true) { + for (let c = 0; c < 2; c++) { + if (!matrix.isReserved(row, col - c)) { + let dark = false; + if (byteIndex < data.length) { + dark = (data[byteIndex] >>> bitIndex & 1) === 1; + } + matrix.set(row, col - c, dark); + bitIndex--; + if (bitIndex === -1) { + byteIndex++; + bitIndex = 7; + } + } + } + row += inc; + if (row < 0 || size <= row) { + row -= inc; + inc = -inc; + break; + } + } + } + } + function createData(version, errorCorrectionLevel, segments) { + const buffer = new BitBuffer(); + segments.forEach(function(data) { + buffer.put(data.mode.bit, 4); + buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version)); + data.write(buffer); + }); + const totalCodewords = Utils.getSymbolTotalCodewords(version); + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel); + const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8; + if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) { + buffer.put(0, 4); + } + while (buffer.getLengthInBits() % 8 !== 0) { + buffer.putBit(0); + } + const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8; + for (let i = 0; i < remainingByte; i++) { + buffer.put(i % 2 ? 17 : 236, 8); + } + return createCodewords(buffer, version, errorCorrectionLevel); + } + function createCodewords(bitBuffer, version, errorCorrectionLevel) { + const totalCodewords = Utils.getSymbolTotalCodewords(version); + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel); + const dataTotalCodewords = totalCodewords - ecTotalCodewords; + const ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel); + const blocksInGroup2 = totalCodewords % ecTotalBlocks; + const blocksInGroup1 = ecTotalBlocks - blocksInGroup2; + const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks); + const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks); + const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1; + const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1; + const rs = new ReedSolomonEncoder(ecCount); + let offset = 0; + const dcData = new Array(ecTotalBlocks); + const ecData = new Array(ecTotalBlocks); + let maxDataSize = 0; + const buffer = new Uint8Array(bitBuffer.buffer); + for (let b = 0; b < ecTotalBlocks; b++) { + const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2; + dcData[b] = buffer.slice(offset, offset + dataSize); + ecData[b] = rs.encode(dcData[b]); + offset += dataSize; + maxDataSize = Math.max(maxDataSize, dataSize); + } + const data = new Uint8Array(totalCodewords); + let index = 0; + let i, r; + for (i = 0; i < maxDataSize; i++) { + for (r = 0; r < ecTotalBlocks; r++) { + if (i < dcData[r].length) { + data[index++] = dcData[r][i]; + } + } + } + for (i = 0; i < ecCount; i++) { + for (r = 0; r < ecTotalBlocks; r++) { + data[index++] = ecData[r][i]; + } + } + return data; + } + function createSymbol(data, version, errorCorrectionLevel, maskPattern) { + let segments; + if (Array.isArray(data)) { + segments = Segments.fromArray(data); + } else if (typeof data === "string") { + let estimatedVersion = version; + if (!estimatedVersion) { + const rawSegments = Segments.rawSplit(data); + estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel); + } + segments = Segments.fromString(data, estimatedVersion || 40); + } else { + throw new Error("Invalid data"); + } + const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel); + if (!bestVersion) { + throw new Error("The amount of data is too big to be stored in a QR Code"); + } + if (!version) { + version = bestVersion; + } else if (version < bestVersion) { + throw new Error( + "\nThe chosen QR Code version cannot contain this amount of data.\nMinimum version required to store current data is: " + bestVersion + ".\n" + ); + } + const dataBits = createData(version, errorCorrectionLevel, segments); + const moduleCount = Utils.getSymbolSize(version); + const modules = new BitMatrix(moduleCount); + setupFinderPattern(modules, version); + setupTimingPattern(modules); + setupAlignmentPattern(modules, version); + setupFormatInfo(modules, errorCorrectionLevel, 0); + if (version >= 7) { + setupVersionInfo(modules, version); + } + setupData(modules, dataBits); + if (isNaN(maskPattern)) { + maskPattern = MaskPattern.getBestMask( + modules, + setupFormatInfo.bind(null, modules, errorCorrectionLevel) + ); + } + MaskPattern.applyMask(maskPattern, modules); + setupFormatInfo(modules, errorCorrectionLevel, maskPattern); + return { + modules, + version, + errorCorrectionLevel, + maskPattern, + segments + }; + } + exports.create = function create(data, options) { + if (typeof data === "undefined" || data === "") { + throw new Error("No input text"); + } + let errorCorrectionLevel = ECLevel.M; + let version; + let mask; + if (typeof options !== "undefined") { + errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M); + version = Version.from(options.version); + mask = MaskPattern.from(options.maskPattern); + if (options.toSJISFunc) { + Utils.setToSJISFunction(options.toSJISFunc); + } + } + return createSymbol(data, version, errorCorrectionLevel, mask); + }; + } +}); + +// node_modules/qrcode/lib/renderer/utils.js +var require_utils2 = __commonJS({ + "node_modules/qrcode/lib/renderer/utils.js"(exports) { + function hex2rgba(hex) { + if (typeof hex === "number") { + hex = hex.toString(); + } + if (typeof hex !== "string") { + throw new Error("Color should be defined as hex string"); + } + let hexCode = hex.slice().replace("#", "").split(""); + if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) { + throw new Error("Invalid hex color: " + hex); + } + if (hexCode.length === 3 || hexCode.length === 4) { + hexCode = Array.prototype.concat.apply([], hexCode.map(function(c) { + return [c, c]; + })); + } + if (hexCode.length === 6) hexCode.push("F", "F"); + const hexValue = parseInt(hexCode.join(""), 16); + return { + r: hexValue >> 24 & 255, + g: hexValue >> 16 & 255, + b: hexValue >> 8 & 255, + a: hexValue & 255, + hex: "#" + hexCode.slice(0, 6).join("") + }; + } + exports.getOptions = function getOptions(options) { + if (!options) options = {}; + if (!options.color) options.color = {}; + const margin = typeof options.margin === "undefined" || options.margin === null || options.margin < 0 ? 4 : options.margin; + const width = options.width && options.width >= 21 ? options.width : void 0; + const scale = options.scale || 4; + return { + width, + scale: width ? 4 : scale, + margin, + color: { + dark: hex2rgba(options.color.dark || "#000000ff"), + light: hex2rgba(options.color.light || "#ffffffff") + }, + type: options.type, + rendererOpts: options.rendererOpts || {} + }; + }; + exports.getScale = function getScale(qrSize, opts) { + return opts.width && opts.width >= qrSize + opts.margin * 2 ? opts.width / (qrSize + opts.margin * 2) : opts.scale; + }; + exports.getImageWidth = function getImageWidth(qrSize, opts) { + const scale = exports.getScale(qrSize, opts); + return Math.floor((qrSize + opts.margin * 2) * scale); + }; + exports.qrToImageData = function qrToImageData(imgData, qr, opts) { + const size = qr.modules.size; + const data = qr.modules.data; + const scale = exports.getScale(size, opts); + const symbolSize = Math.floor((size + opts.margin * 2) * scale); + const scaledMargin = opts.margin * scale; + const palette = [opts.color.light, opts.color.dark]; + for (let i = 0; i < symbolSize; i++) { + for (let j = 0; j < symbolSize; j++) { + let posDst = (i * symbolSize + j) * 4; + let pxColor = opts.color.light; + if (i >= scaledMargin && j >= scaledMargin && i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) { + const iSrc = Math.floor((i - scaledMargin) / scale); + const jSrc = Math.floor((j - scaledMargin) / scale); + pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0]; + } + imgData[posDst++] = pxColor.r; + imgData[posDst++] = pxColor.g; + imgData[posDst++] = pxColor.b; + imgData[posDst] = pxColor.a; + } + } + }; + } +}); + +// node_modules/qrcode/lib/renderer/canvas.js +var require_canvas = __commonJS({ + "node_modules/qrcode/lib/renderer/canvas.js"(exports) { + var Utils = require_utils2(); + function clearCanvas(ctx, canvas, size) { + ctx.clearRect(0, 0, canvas.width, canvas.height); + if (!canvas.style) canvas.style = {}; + canvas.height = size; + canvas.width = size; + canvas.style.height = size + "px"; + canvas.style.width = size + "px"; + } + function getCanvasElement() { + try { + return document.createElement("canvas"); + } catch (e) { + throw new Error("You need to specify a canvas element"); + } + } + exports.render = function render(qrData, canvas, options) { + let opts = options; + let canvasEl = canvas; + if (typeof opts === "undefined" && (!canvas || !canvas.getContext)) { + opts = canvas; + canvas = void 0; + } + if (!canvas) { + canvasEl = getCanvasElement(); + } + opts = Utils.getOptions(opts); + const size = Utils.getImageWidth(qrData.modules.size, opts); + const ctx = canvasEl.getContext("2d"); + const image = ctx.createImageData(size, size); + Utils.qrToImageData(image.data, qrData, opts); + clearCanvas(ctx, canvasEl, size); + ctx.putImageData(image, 0, 0); + return canvasEl; + }; + exports.renderToDataURL = function renderToDataURL(qrData, canvas, options) { + let opts = options; + if (typeof opts === "undefined" && (!canvas || !canvas.getContext)) { + opts = canvas; + canvas = void 0; + } + if (!opts) opts = {}; + const canvasEl = exports.render(qrData, canvas, opts); + const type = opts.type || "image/png"; + const rendererOpts = opts.rendererOpts || {}; + return canvasEl.toDataURL(type, rendererOpts.quality); + }; + } +}); + +// node_modules/qrcode/lib/renderer/svg-tag.js +var require_svg_tag = __commonJS({ + "node_modules/qrcode/lib/renderer/svg-tag.js"(exports) { + var Utils = require_utils2(); + function getColorAttrib(color, attrib) { + const alpha = color.a / 255; + const str = attrib + '="' + color.hex + '"'; + return alpha < 1 ? str + " " + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"' : str; + } + function svgCmd(cmd, x, y) { + let str = cmd + x; + if (typeof y !== "undefined") str += " " + y; + return str; + } + function qrToPath(data, size, margin) { + let path = ""; + let moveBy = 0; + let newRow = false; + let lineLength = 0; + for (let i = 0; i < data.length; i++) { + const col = Math.floor(i % size); + const row = Math.floor(i / size); + if (!col && !newRow) newRow = true; + if (data[i]) { + lineLength++; + if (!(i > 0 && col > 0 && data[i - 1])) { + path += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0); + moveBy = 0; + newRow = false; + } + if (!(col + 1 < size && data[i + 1])) { + path += svgCmd("h", lineLength); + lineLength = 0; + } + } else { + moveBy++; + } + } + return path; + } + exports.render = function render(qrData, options, cb) { + const opts = Utils.getOptions(options); + const size = qrData.modules.size; + const data = qrData.modules.data; + const qrcodesize = size + opts.margin * 2; + const bg = !opts.color.light.a ? "" : "'; + const path = "'; + const viewBox = 'viewBox="0 0 ' + qrcodesize + " " + qrcodesize + '"'; + const width = !opts.width ? "" : 'width="' + opts.width + '" height="' + opts.width + '" '; + const svgTag = '' + bg + path + "\n"; + if (typeof cb === "function") { + cb(null, svgTag); + } + return svgTag; + }; + } +}); + +// node_modules/qrcode/lib/browser.js +var require_browser = __commonJS({ + "node_modules/qrcode/lib/browser.js"(exports) { + var canPromise = require_can_promise(); + var QRCode2 = require_qrcode(); + var CanvasRenderer = require_canvas(); + var SvgRenderer = require_svg_tag(); + function renderCanvas(renderFunc, canvas, text, opts, cb) { + const args = [].slice.call(arguments, 1); + const argsNum = args.length; + const isLastArgCb = typeof args[argsNum - 1] === "function"; + if (!isLastArgCb && !canPromise()) { + throw new Error("Callback required as last argument"); + } + if (isLastArgCb) { + if (argsNum < 2) { + throw new Error("Too few arguments provided"); + } + if (argsNum === 2) { + cb = text; + text = canvas; + canvas = opts = void 0; + } else if (argsNum === 3) { + if (canvas.getContext && typeof cb === "undefined") { + cb = opts; + opts = void 0; + } else { + cb = opts; + opts = text; + text = canvas; + canvas = void 0; + } + } + } else { + if (argsNum < 1) { + throw new Error("Too few arguments provided"); + } + if (argsNum === 1) { + text = canvas; + canvas = opts = void 0; + } else if (argsNum === 2 && !canvas.getContext) { + opts = text; + text = canvas; + canvas = void 0; + } + return new Promise(function(resolve, reject) { + try { + const data = QRCode2.create(text, opts); + resolve(renderFunc(data, canvas, opts)); + } catch (e) { + reject(e); + } + }); + } + try { + const data = QRCode2.create(text, opts); + cb(null, renderFunc(data, canvas, opts)); + } catch (e) { + cb(e); + } + } + exports.create = QRCode2.create; + exports.toCanvas = renderCanvas.bind(null, CanvasRenderer.render); + exports.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL); + exports.toString = renderCanvas.bind(null, function(data, _, opts) { + return SvgRenderer.render(data, opts); + }); + } +}); + +// src/scripts/qr-local.js +var QRCode = __toESM(require_browser()); +async function generateQRCode(text, opts = {}) { + const size = opts.size || 300; + const margin = opts.margin ?? 2; + const errorCorrectionLevel = opts.errorCorrectionLevel || "M"; + return await QRCode.toDataURL(text, { width: size, margin, errorCorrectionLevel }); +} +window.generateQRCode = generateQRCode; +//# sourceMappingURL=qr-local.js.map diff --git a/dist/qr-local.js.map b/dist/qr-local.js.map new file mode 100644 index 0000000..040c533 --- /dev/null +++ b/dist/qr-local.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../node_modules/qrcode/lib/can-promise.js", "../node_modules/qrcode/lib/core/utils.js", "../node_modules/qrcode/lib/core/error-correction-level.js", "../node_modules/qrcode/lib/core/bit-buffer.js", "../node_modules/qrcode/lib/core/bit-matrix.js", "../node_modules/qrcode/lib/core/alignment-pattern.js", "../node_modules/qrcode/lib/core/finder-pattern.js", "../node_modules/qrcode/lib/core/mask-pattern.js", "../node_modules/qrcode/lib/core/error-correction-code.js", "../node_modules/qrcode/lib/core/galois-field.js", "../node_modules/qrcode/lib/core/polynomial.js", "../node_modules/qrcode/lib/core/reed-solomon-encoder.js", "../node_modules/qrcode/lib/core/version-check.js", "../node_modules/qrcode/lib/core/regex.js", "../node_modules/qrcode/lib/core/mode.js", "../node_modules/qrcode/lib/core/version.js", "../node_modules/qrcode/lib/core/format-info.js", "../node_modules/qrcode/lib/core/numeric-data.js", "../node_modules/qrcode/lib/core/alphanumeric-data.js", "../node_modules/qrcode/lib/core/byte-data.js", "../node_modules/qrcode/lib/core/kanji-data.js", "../node_modules/dijkstrajs/dijkstra.js", "../node_modules/qrcode/lib/core/segments.js", "../node_modules/qrcode/lib/core/qrcode.js", "../node_modules/qrcode/lib/renderer/utils.js", "../node_modules/qrcode/lib/renderer/canvas.js", "../node_modules/qrcode/lib/renderer/svg-tag.js", "../node_modules/qrcode/lib/browser.js", "../src/scripts/qr-local.js"], + "sourcesContent": ["// can-promise has a crash in some versions of react native that dont have\n// standard global objects\n// https://github.com/soldair/node-qrcode/issues/157\n\nmodule.exports = function () {\n return typeof Promise === 'function' && Promise.prototype && Promise.prototype.then\n}\n", "let toSJISFunction\nconst CODEWORDS_COUNT = [\n 0, // Not used\n 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,\n 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085,\n 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185,\n 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706\n]\n\n/**\n * Returns the QR Code size for the specified version\n *\n * @param {Number} version QR Code version\n * @return {Number} size of QR code\n */\nexports.getSymbolSize = function getSymbolSize (version) {\n if (!version) throw new Error('\"version\" cannot be null or undefined')\n if (version < 1 || version > 40) throw new Error('\"version\" should be in range from 1 to 40')\n return version * 4 + 17\n}\n\n/**\n * Returns the total number of codewords used to store data and EC information.\n *\n * @param {Number} version QR Code version\n * @return {Number} Data length in bits\n */\nexports.getSymbolTotalCodewords = function getSymbolTotalCodewords (version) {\n return CODEWORDS_COUNT[version]\n}\n\n/**\n * Encode data with Bose-Chaudhuri-Hocquenghem\n *\n * @param {Number} data Value to encode\n * @return {Number} Encoded value\n */\nexports.getBCHDigit = function (data) {\n let digit = 0\n\n while (data !== 0) {\n digit++\n data >>>= 1\n }\n\n return digit\n}\n\nexports.setToSJISFunction = function setToSJISFunction (f) {\n if (typeof f !== 'function') {\n throw new Error('\"toSJISFunc\" is not a valid function.')\n }\n\n toSJISFunction = f\n}\n\nexports.isKanjiModeEnabled = function () {\n return typeof toSJISFunction !== 'undefined'\n}\n\nexports.toSJIS = function toSJIS (kanji) {\n return toSJISFunction(kanji)\n}\n", "exports.L = { bit: 1 }\nexports.M = { bit: 0 }\nexports.Q = { bit: 3 }\nexports.H = { bit: 2 }\n\nfunction fromString (string) {\n if (typeof string !== 'string') {\n throw new Error('Param is not a string')\n }\n\n const lcStr = string.toLowerCase()\n\n switch (lcStr) {\n case 'l':\n case 'low':\n return exports.L\n\n case 'm':\n case 'medium':\n return exports.M\n\n case 'q':\n case 'quartile':\n return exports.Q\n\n case 'h':\n case 'high':\n return exports.H\n\n default:\n throw new Error('Unknown EC Level: ' + string)\n }\n}\n\nexports.isValid = function isValid (level) {\n return level && typeof level.bit !== 'undefined' &&\n level.bit >= 0 && level.bit < 4\n}\n\nexports.from = function from (value, defaultValue) {\n if (exports.isValid(value)) {\n return value\n }\n\n try {\n return fromString(value)\n } catch (e) {\n return defaultValue\n }\n}\n", "function BitBuffer () {\n this.buffer = []\n this.length = 0\n}\n\nBitBuffer.prototype = {\n\n get: function (index) {\n const bufIndex = Math.floor(index / 8)\n return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) === 1\n },\n\n put: function (num, length) {\n for (let i = 0; i < length; i++) {\n this.putBit(((num >>> (length - i - 1)) & 1) === 1)\n }\n },\n\n getLengthInBits: function () {\n return this.length\n },\n\n putBit: function (bit) {\n const bufIndex = Math.floor(this.length / 8)\n if (this.buffer.length <= bufIndex) {\n this.buffer.push(0)\n }\n\n if (bit) {\n this.buffer[bufIndex] |= (0x80 >>> (this.length % 8))\n }\n\n this.length++\n }\n}\n\nmodule.exports = BitBuffer\n", "/**\n * Helper class to handle QR Code symbol modules\n *\n * @param {Number} size Symbol size\n */\nfunction BitMatrix (size) {\n if (!size || size < 1) {\n throw new Error('BitMatrix size must be defined and greater than 0')\n }\n\n this.size = size\n this.data = new Uint8Array(size * size)\n this.reservedBit = new Uint8Array(size * size)\n}\n\n/**\n * Set bit value at specified location\n * If reserved flag is set, this bit will be ignored during masking process\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n * @param {Boolean} reserved\n */\nBitMatrix.prototype.set = function (row, col, value, reserved) {\n const index = row * this.size + col\n this.data[index] = value\n if (reserved) this.reservedBit[index] = true\n}\n\n/**\n * Returns bit value at specified location\n *\n * @param {Number} row\n * @param {Number} col\n * @return {Boolean}\n */\nBitMatrix.prototype.get = function (row, col) {\n return this.data[row * this.size + col]\n}\n\n/**\n * Applies xor operator at specified location\n * (used during masking process)\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n */\nBitMatrix.prototype.xor = function (row, col, value) {\n this.data[row * this.size + col] ^= value\n}\n\n/**\n * Check if bit at specified location is reserved\n *\n * @param {Number} row\n * @param {Number} col\n * @return {Boolean}\n */\nBitMatrix.prototype.isReserved = function (row, col) {\n return this.reservedBit[row * this.size + col]\n}\n\nmodule.exports = BitMatrix\n", "/**\n * Alignment pattern are fixed reference pattern in defined positions\n * in a matrix symbology, which enables the decode software to re-synchronise\n * the coordinate mapping of the image modules in the event of moderate amounts\n * of distortion of the image.\n *\n * Alignment patterns are present only in QR Code symbols of version 2 or larger\n * and their number depends on the symbol version.\n */\n\nconst getSymbolSize = require('./utils').getSymbolSize\n\n/**\n * Calculate the row/column coordinates of the center module of each alignment pattern\n * for the specified QR Code version.\n *\n * The alignment patterns are positioned symmetrically on either side of the diagonal\n * running from the top left corner of the symbol to the bottom right corner.\n *\n * Since positions are simmetrical only half of the coordinates are returned.\n * Each item of the array will represent in turn the x and y coordinate.\n * @see {@link getPositions}\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinate\n */\nexports.getRowColCoords = function getRowColCoords (version) {\n if (version === 1) return []\n\n const posCount = Math.floor(version / 7) + 2\n const size = getSymbolSize(version)\n const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2\n const positions = [size - 7] // Last coord is always (size - 7)\n\n for (let i = 1; i < posCount - 1; i++) {\n positions[i] = positions[i - 1] - intervals\n }\n\n positions.push(6) // First coord is always 6\n\n return positions.reverse()\n}\n\n/**\n * Returns an array containing the positions of each alignment pattern.\n * Each array's element represent the center point of the pattern as (x, y) coordinates\n *\n * Coordinates are calculated expanding the row/column coordinates returned by {@link getRowColCoords}\n * and filtering out the items that overlaps with finder pattern\n *\n * @example\n * For a Version 7 symbol {@link getRowColCoords} returns values 6, 22 and 38.\n * The alignment patterns, therefore, are to be centered on (row, column)\n * positions (6,22), (22,6), (22,22), (22,38), (38,22), (38,38).\n * Note that the coordinates (6,6), (6,38), (38,6) are occupied by finder patterns\n * and are not therefore used for alignment patterns.\n *\n * let pos = getPositions(7)\n * // [[6,22], [22,6], [22,22], [22,38], [38,22], [38,38]]\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinates\n */\nexports.getPositions = function getPositions (version) {\n const coords = []\n const pos = exports.getRowColCoords(version)\n const posLength = pos.length\n\n for (let i = 0; i < posLength; i++) {\n for (let j = 0; j < posLength; j++) {\n // Skip if position is occupied by finder patterns\n if ((i === 0 && j === 0) || // top-left\n (i === 0 && j === posLength - 1) || // bottom-left\n (i === posLength - 1 && j === 0)) { // top-right\n continue\n }\n\n coords.push([pos[i], pos[j]])\n }\n }\n\n return coords\n}\n", "const getSymbolSize = require('./utils').getSymbolSize\nconst FINDER_PATTERN_SIZE = 7\n\n/**\n * Returns an array containing the positions of each finder pattern.\n * Each array's element represent the top-left point of the pattern as (x, y) coordinates\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinates\n */\nexports.getPositions = function getPositions (version) {\n const size = getSymbolSize(version)\n\n return [\n // top-left\n [0, 0],\n // top-right\n [size - FINDER_PATTERN_SIZE, 0],\n // bottom-left\n [0, size - FINDER_PATTERN_SIZE]\n ]\n}\n", "/**\n * Data mask pattern reference\n * @type {Object}\n */\nexports.Patterns = {\n PATTERN000: 0,\n PATTERN001: 1,\n PATTERN010: 2,\n PATTERN011: 3,\n PATTERN100: 4,\n PATTERN101: 5,\n PATTERN110: 6,\n PATTERN111: 7\n}\n\n/**\n * Weighted penalty scores for the undesirable features\n * @type {Object}\n */\nconst PenaltyScores = {\n N1: 3,\n N2: 3,\n N3: 40,\n N4: 10\n}\n\n/**\n * Check if mask pattern value is valid\n *\n * @param {Number} mask Mask pattern\n * @return {Boolean} true if valid, false otherwise\n */\nexports.isValid = function isValid (mask) {\n return mask != null && mask !== '' && !isNaN(mask) && mask >= 0 && mask <= 7\n}\n\n/**\n * Returns mask pattern from a value.\n * If value is not valid, returns undefined\n *\n * @param {Number|String} value Mask pattern value\n * @return {Number} Valid mask pattern or undefined\n */\nexports.from = function from (value) {\n return exports.isValid(value) ? parseInt(value, 10) : undefined\n}\n\n/**\n* Find adjacent modules in row/column with the same color\n* and assign a penalty value.\n*\n* Points: N1 + i\n* i is the amount by which the number of adjacent modules of the same color exceeds 5\n*/\nexports.getPenaltyN1 = function getPenaltyN1 (data) {\n const size = data.size\n let points = 0\n let sameCountCol = 0\n let sameCountRow = 0\n let lastCol = null\n let lastRow = null\n\n for (let row = 0; row < size; row++) {\n sameCountCol = sameCountRow = 0\n lastCol = lastRow = null\n\n for (let col = 0; col < size; col++) {\n let module = data.get(row, col)\n if (module === lastCol) {\n sameCountCol++\n } else {\n if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5)\n lastCol = module\n sameCountCol = 1\n }\n\n module = data.get(col, row)\n if (module === lastRow) {\n sameCountRow++\n } else {\n if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5)\n lastRow = module\n sameCountRow = 1\n }\n }\n\n if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5)\n if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5)\n }\n\n return points\n}\n\n/**\n * Find 2x2 blocks with the same color and assign a penalty value\n *\n * Points: N2 * (m - 1) * (n - 1)\n */\nexports.getPenaltyN2 = function getPenaltyN2 (data) {\n const size = data.size\n let points = 0\n\n for (let row = 0; row < size - 1; row++) {\n for (let col = 0; col < size - 1; col++) {\n const last = data.get(row, col) +\n data.get(row, col + 1) +\n data.get(row + 1, col) +\n data.get(row + 1, col + 1)\n\n if (last === 4 || last === 0) points++\n }\n }\n\n return points * PenaltyScores.N2\n}\n\n/**\n * Find 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column,\n * preceded or followed by light area 4 modules wide\n *\n * Points: N3 * number of pattern found\n */\nexports.getPenaltyN3 = function getPenaltyN3 (data) {\n const size = data.size\n let points = 0\n let bitsCol = 0\n let bitsRow = 0\n\n for (let row = 0; row < size; row++) {\n bitsCol = bitsRow = 0\n for (let col = 0; col < size; col++) {\n bitsCol = ((bitsCol << 1) & 0x7FF) | data.get(row, col)\n if (col >= 10 && (bitsCol === 0x5D0 || bitsCol === 0x05D)) points++\n\n bitsRow = ((bitsRow << 1) & 0x7FF) | data.get(col, row)\n if (col >= 10 && (bitsRow === 0x5D0 || bitsRow === 0x05D)) points++\n }\n }\n\n return points * PenaltyScores.N3\n}\n\n/**\n * Calculate proportion of dark modules in entire symbol\n *\n * Points: N4 * k\n *\n * k is the rating of the deviation of the proportion of dark modules\n * in the symbol from 50% in steps of 5%\n */\nexports.getPenaltyN4 = function getPenaltyN4 (data) {\n let darkCount = 0\n const modulesCount = data.data.length\n\n for (let i = 0; i < modulesCount; i++) darkCount += data.data[i]\n\n const k = Math.abs(Math.ceil((darkCount * 100 / modulesCount) / 5) - 10)\n\n return k * PenaltyScores.N4\n}\n\n/**\n * Return mask value at given position\n *\n * @param {Number} maskPattern Pattern reference value\n * @param {Number} i Row\n * @param {Number} j Column\n * @return {Boolean} Mask value\n */\nfunction getMaskAt (maskPattern, i, j) {\n switch (maskPattern) {\n case exports.Patterns.PATTERN000: return (i + j) % 2 === 0\n case exports.Patterns.PATTERN001: return i % 2 === 0\n case exports.Patterns.PATTERN010: return j % 3 === 0\n case exports.Patterns.PATTERN011: return (i + j) % 3 === 0\n case exports.Patterns.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0\n case exports.Patterns.PATTERN101: return (i * j) % 2 + (i * j) % 3 === 0\n case exports.Patterns.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 === 0\n case exports.Patterns.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 === 0\n\n default: throw new Error('bad maskPattern:' + maskPattern)\n }\n}\n\n/**\n * Apply a mask pattern to a BitMatrix\n *\n * @param {Number} pattern Pattern reference number\n * @param {BitMatrix} data BitMatrix data\n */\nexports.applyMask = function applyMask (pattern, data) {\n const size = data.size\n\n for (let col = 0; col < size; col++) {\n for (let row = 0; row < size; row++) {\n if (data.isReserved(row, col)) continue\n data.xor(row, col, getMaskAt(pattern, row, col))\n }\n }\n}\n\n/**\n * Returns the best mask pattern for data\n *\n * @param {BitMatrix} data\n * @return {Number} Mask pattern reference number\n */\nexports.getBestMask = function getBestMask (data, setupFormatFunc) {\n const numPatterns = Object.keys(exports.Patterns).length\n let bestPattern = 0\n let lowerPenalty = Infinity\n\n for (let p = 0; p < numPatterns; p++) {\n setupFormatFunc(p)\n exports.applyMask(p, data)\n\n // Calculate penalty\n const penalty =\n exports.getPenaltyN1(data) +\n exports.getPenaltyN2(data) +\n exports.getPenaltyN3(data) +\n exports.getPenaltyN4(data)\n\n // Undo previously applied mask\n exports.applyMask(p, data)\n\n if (penalty < lowerPenalty) {\n lowerPenalty = penalty\n bestPattern = p\n }\n }\n\n return bestPattern\n}\n", "const ECLevel = require('./error-correction-level')\r\n\r\nconst EC_BLOCKS_TABLE = [\r\n// L M Q H\r\n 1, 1, 1, 1,\r\n 1, 1, 1, 1,\r\n 1, 1, 2, 2,\r\n 1, 2, 2, 4,\r\n 1, 2, 4, 4,\r\n 2, 4, 4, 4,\r\n 2, 4, 6, 5,\r\n 2, 4, 6, 6,\r\n 2, 5, 8, 8,\r\n 4, 5, 8, 8,\r\n 4, 5, 8, 11,\r\n 4, 8, 10, 11,\r\n 4, 9, 12, 16,\r\n 4, 9, 16, 16,\r\n 6, 10, 12, 18,\r\n 6, 10, 17, 16,\r\n 6, 11, 16, 19,\r\n 6, 13, 18, 21,\r\n 7, 14, 21, 25,\r\n 8, 16, 20, 25,\r\n 8, 17, 23, 25,\r\n 9, 17, 23, 34,\r\n 9, 18, 25, 30,\r\n 10, 20, 27, 32,\r\n 12, 21, 29, 35,\r\n 12, 23, 34, 37,\r\n 12, 25, 34, 40,\r\n 13, 26, 35, 42,\r\n 14, 28, 38, 45,\r\n 15, 29, 40, 48,\r\n 16, 31, 43, 51,\r\n 17, 33, 45, 54,\r\n 18, 35, 48, 57,\r\n 19, 37, 51, 60,\r\n 19, 38, 53, 63,\r\n 20, 40, 56, 66,\r\n 21, 43, 59, 70,\r\n 22, 45, 62, 74,\r\n 24, 47, 65, 77,\r\n 25, 49, 68, 81\r\n]\r\n\r\nconst EC_CODEWORDS_TABLE = [\r\n// L M Q H\r\n 7, 10, 13, 17,\r\n 10, 16, 22, 28,\r\n 15, 26, 36, 44,\r\n 20, 36, 52, 64,\r\n 26, 48, 72, 88,\r\n 36, 64, 96, 112,\r\n 40, 72, 108, 130,\r\n 48, 88, 132, 156,\r\n 60, 110, 160, 192,\r\n 72, 130, 192, 224,\r\n 80, 150, 224, 264,\r\n 96, 176, 260, 308,\r\n 104, 198, 288, 352,\r\n 120, 216, 320, 384,\r\n 132, 240, 360, 432,\r\n 144, 280, 408, 480,\r\n 168, 308, 448, 532,\r\n 180, 338, 504, 588,\r\n 196, 364, 546, 650,\r\n 224, 416, 600, 700,\r\n 224, 442, 644, 750,\r\n 252, 476, 690, 816,\r\n 270, 504, 750, 900,\r\n 300, 560, 810, 960,\r\n 312, 588, 870, 1050,\r\n 336, 644, 952, 1110,\r\n 360, 700, 1020, 1200,\r\n 390, 728, 1050, 1260,\r\n 420, 784, 1140, 1350,\r\n 450, 812, 1200, 1440,\r\n 480, 868, 1290, 1530,\r\n 510, 924, 1350, 1620,\r\n 540, 980, 1440, 1710,\r\n 570, 1036, 1530, 1800,\r\n 570, 1064, 1590, 1890,\r\n 600, 1120, 1680, 1980,\r\n 630, 1204, 1770, 2100,\r\n 660, 1260, 1860, 2220,\r\n 720, 1316, 1950, 2310,\r\n 750, 1372, 2040, 2430\r\n]\r\n\r\n/**\r\n * Returns the number of error correction block that the QR Code should contain\r\n * for the specified version and error correction level.\r\n *\r\n * @param {Number} version QR Code version\r\n * @param {Number} errorCorrectionLevel Error correction level\r\n * @return {Number} Number of error correction blocks\r\n */\r\nexports.getBlocksCount = function getBlocksCount (version, errorCorrectionLevel) {\r\n switch (errorCorrectionLevel) {\r\n case ECLevel.L:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 0]\r\n case ECLevel.M:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 1]\r\n case ECLevel.Q:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 2]\r\n case ECLevel.H:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 3]\r\n default:\r\n return undefined\r\n }\r\n}\r\n\r\n/**\r\n * Returns the number of error correction codewords to use for the specified\r\n * version and error correction level.\r\n *\r\n * @param {Number} version QR Code version\r\n * @param {Number} errorCorrectionLevel Error correction level\r\n * @return {Number} Number of error correction codewords\r\n */\r\nexports.getTotalCodewordsCount = function getTotalCodewordsCount (version, errorCorrectionLevel) {\r\n switch (errorCorrectionLevel) {\r\n case ECLevel.L:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0]\r\n case ECLevel.M:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1]\r\n case ECLevel.Q:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2]\r\n case ECLevel.H:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3]\r\n default:\r\n return undefined\r\n }\r\n}\r\n", "const EXP_TABLE = new Uint8Array(512)\nconst LOG_TABLE = new Uint8Array(256)\n/**\n * Precompute the log and anti-log tables for faster computation later\n *\n * For each possible value in the galois field 2^8, we will pre-compute\n * the logarithm and anti-logarithm (exponential) of this value\n *\n * ref {@link https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Introduction_to_mathematical_fields}\n */\n;(function initTables () {\n let x = 1\n for (let i = 0; i < 255; i++) {\n EXP_TABLE[i] = x\n LOG_TABLE[x] = i\n\n x <<= 1 // multiply by 2\n\n // The QR code specification says to use byte-wise modulo 100011101 arithmetic.\n // This means that when a number is 256 or larger, it should be XORed with 0x11D.\n if (x & 0x100) { // similar to x >= 256, but a lot faster (because 0x100 == 256)\n x ^= 0x11D\n }\n }\n\n // Optimization: double the size of the anti-log table so that we don't need to mod 255 to\n // stay inside the bounds (because we will mainly use this table for the multiplication of\n // two GF numbers, no more).\n // @see {@link mul}\n for (let i = 255; i < 512; i++) {\n EXP_TABLE[i] = EXP_TABLE[i - 255]\n }\n}())\n\n/**\n * Returns log value of n inside Galois Field\n *\n * @param {Number} n\n * @return {Number}\n */\nexports.log = function log (n) {\n if (n < 1) throw new Error('log(' + n + ')')\n return LOG_TABLE[n]\n}\n\n/**\n * Returns anti-log value of n inside Galois Field\n *\n * @param {Number} n\n * @return {Number}\n */\nexports.exp = function exp (n) {\n return EXP_TABLE[n]\n}\n\n/**\n * Multiplies two number inside Galois Field\n *\n * @param {Number} x\n * @param {Number} y\n * @return {Number}\n */\nexports.mul = function mul (x, y) {\n if (x === 0 || y === 0) return 0\n\n // should be EXP_TABLE[(LOG_TABLE[x] + LOG_TABLE[y]) % 255] if EXP_TABLE wasn't oversized\n // @see {@link initTables}\n return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]]\n}\n", "const GF = require('./galois-field')\n\n/**\n * Multiplies two polynomials inside Galois Field\n *\n * @param {Uint8Array} p1 Polynomial\n * @param {Uint8Array} p2 Polynomial\n * @return {Uint8Array} Product of p1 and p2\n */\nexports.mul = function mul (p1, p2) {\n const coeff = new Uint8Array(p1.length + p2.length - 1)\n\n for (let i = 0; i < p1.length; i++) {\n for (let j = 0; j < p2.length; j++) {\n coeff[i + j] ^= GF.mul(p1[i], p2[j])\n }\n }\n\n return coeff\n}\n\n/**\n * Calculate the remainder of polynomials division\n *\n * @param {Uint8Array} divident Polynomial\n * @param {Uint8Array} divisor Polynomial\n * @return {Uint8Array} Remainder\n */\nexports.mod = function mod (divident, divisor) {\n let result = new Uint8Array(divident)\n\n while ((result.length - divisor.length) >= 0) {\n const coeff = result[0]\n\n for (let i = 0; i < divisor.length; i++) {\n result[i] ^= GF.mul(divisor[i], coeff)\n }\n\n // remove all zeros from buffer head\n let offset = 0\n while (offset < result.length && result[offset] === 0) offset++\n result = result.slice(offset)\n }\n\n return result\n}\n\n/**\n * Generate an irreducible generator polynomial of specified degree\n * (used by Reed-Solomon encoder)\n *\n * @param {Number} degree Degree of the generator polynomial\n * @return {Uint8Array} Buffer containing polynomial coefficients\n */\nexports.generateECPolynomial = function generateECPolynomial (degree) {\n let poly = new Uint8Array([1])\n for (let i = 0; i < degree; i++) {\n poly = exports.mul(poly, new Uint8Array([1, GF.exp(i)]))\n }\n\n return poly\n}\n", "const Polynomial = require('./polynomial')\n\nfunction ReedSolomonEncoder (degree) {\n this.genPoly = undefined\n this.degree = degree\n\n if (this.degree) this.initialize(this.degree)\n}\n\n/**\n * Initialize the encoder.\n * The input param should correspond to the number of error correction codewords.\n *\n * @param {Number} degree\n */\nReedSolomonEncoder.prototype.initialize = function initialize (degree) {\n // create an irreducible generator polynomial\n this.degree = degree\n this.genPoly = Polynomial.generateECPolynomial(this.degree)\n}\n\n/**\n * Encodes a chunk of data\n *\n * @param {Uint8Array} data Buffer containing input data\n * @return {Uint8Array} Buffer containing encoded data\n */\nReedSolomonEncoder.prototype.encode = function encode (data) {\n if (!this.genPoly) {\n throw new Error('Encoder not initialized')\n }\n\n // Calculate EC for this data block\n // extends data size to data+genPoly size\n const paddedData = new Uint8Array(data.length + this.degree)\n paddedData.set(data)\n\n // The error correction codewords are the remainder after dividing the data codewords\n // by a generator polynomial\n const remainder = Polynomial.mod(paddedData, this.genPoly)\n\n // return EC data blocks (last n byte, where n is the degree of genPoly)\n // If coefficients number in remainder are less than genPoly degree,\n // pad with 0s to the left to reach the needed number of coefficients\n const start = this.degree - remainder.length\n if (start > 0) {\n const buff = new Uint8Array(this.degree)\n buff.set(remainder, start)\n\n return buff\n }\n\n return remainder\n}\n\nmodule.exports = ReedSolomonEncoder\n", "/**\n * Check if QR Code version is valid\n *\n * @param {Number} version QR Code version\n * @return {Boolean} true if valid version, false otherwise\n */\nexports.isValid = function isValid (version) {\n return !isNaN(version) && version >= 1 && version <= 40\n}\n", "const numeric = '[0-9]+'\nconst alphanumeric = '[A-Z $%*+\\\\-./:]+'\nlet kanji = '(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|' +\n '[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|' +\n '[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|' +\n '[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+'\nkanji = kanji.replace(/u/g, '\\\\u')\n\nconst byte = '(?:(?![A-Z0-9 $%*+\\\\-./:]|' + kanji + ')(?:.|[\\r\\n]))+'\n\nexports.KANJI = new RegExp(kanji, 'g')\nexports.BYTE_KANJI = new RegExp('[^A-Z0-9 $%*+\\\\-./:]+', 'g')\nexports.BYTE = new RegExp(byte, 'g')\nexports.NUMERIC = new RegExp(numeric, 'g')\nexports.ALPHANUMERIC = new RegExp(alphanumeric, 'g')\n\nconst TEST_KANJI = new RegExp('^' + kanji + '$')\nconst TEST_NUMERIC = new RegExp('^' + numeric + '$')\nconst TEST_ALPHANUMERIC = new RegExp('^[A-Z0-9 $%*+\\\\-./:]+$')\n\nexports.testKanji = function testKanji (str) {\n return TEST_KANJI.test(str)\n}\n\nexports.testNumeric = function testNumeric (str) {\n return TEST_NUMERIC.test(str)\n}\n\nexports.testAlphanumeric = function testAlphanumeric (str) {\n return TEST_ALPHANUMERIC.test(str)\n}\n", "const VersionCheck = require('./version-check')\nconst Regex = require('./regex')\n\n/**\n * Numeric mode encodes data from the decimal digit set (0 - 9)\n * (byte values 30HEX to 39HEX).\n * Normally, 3 data characters are represented by 10 bits.\n *\n * @type {Object}\n */\nexports.NUMERIC = {\n id: 'Numeric',\n bit: 1 << 0,\n ccBits: [10, 12, 14]\n}\n\n/**\n * Alphanumeric mode encodes data from a set of 45 characters,\n * i.e. 10 numeric digits (0 - 9),\n * 26 alphabetic characters (A - Z),\n * and 9 symbols (SP, $, %, *, +, -, ., /, :).\n * Normally, two input characters are represented by 11 bits.\n *\n * @type {Object}\n */\nexports.ALPHANUMERIC = {\n id: 'Alphanumeric',\n bit: 1 << 1,\n ccBits: [9, 11, 13]\n}\n\n/**\n * In byte mode, data is encoded at 8 bits per character.\n *\n * @type {Object}\n */\nexports.BYTE = {\n id: 'Byte',\n bit: 1 << 2,\n ccBits: [8, 16, 16]\n}\n\n/**\n * The Kanji mode efficiently encodes Kanji characters in accordance with\n * the Shift JIS system based on JIS X 0208.\n * The Shift JIS values are shifted from the JIS X 0208 values.\n * JIS X 0208 gives details of the shift coded representation.\n * Each two-byte character value is compacted to a 13-bit binary codeword.\n *\n * @type {Object}\n */\nexports.KANJI = {\n id: 'Kanji',\n bit: 1 << 3,\n ccBits: [8, 10, 12]\n}\n\n/**\n * Mixed mode will contain a sequences of data in a combination of any of\n * the modes described above\n *\n * @type {Object}\n */\nexports.MIXED = {\n bit: -1\n}\n\n/**\n * Returns the number of bits needed to store the data length\n * according to QR Code specifications.\n *\n * @param {Mode} mode Data mode\n * @param {Number} version QR Code version\n * @return {Number} Number of bits\n */\nexports.getCharCountIndicator = function getCharCountIndicator (mode, version) {\n if (!mode.ccBits) throw new Error('Invalid mode: ' + mode)\n\n if (!VersionCheck.isValid(version)) {\n throw new Error('Invalid version: ' + version)\n }\n\n if (version >= 1 && version < 10) return mode.ccBits[0]\n else if (version < 27) return mode.ccBits[1]\n return mode.ccBits[2]\n}\n\n/**\n * Returns the most efficient mode to store the specified data\n *\n * @param {String} dataStr Input data string\n * @return {Mode} Best mode\n */\nexports.getBestModeForData = function getBestModeForData (dataStr) {\n if (Regex.testNumeric(dataStr)) return exports.NUMERIC\n else if (Regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC\n else if (Regex.testKanji(dataStr)) return exports.KANJI\n else return exports.BYTE\n}\n\n/**\n * Return mode name as string\n *\n * @param {Mode} mode Mode object\n * @returns {String} Mode name\n */\nexports.toString = function toString (mode) {\n if (mode && mode.id) return mode.id\n throw new Error('Invalid mode')\n}\n\n/**\n * Check if input param is a valid mode object\n *\n * @param {Mode} mode Mode object\n * @returns {Boolean} True if valid mode, false otherwise\n */\nexports.isValid = function isValid (mode) {\n return mode && mode.bit && mode.ccBits\n}\n\n/**\n * Get mode object from its name\n *\n * @param {String} string Mode name\n * @returns {Mode} Mode object\n */\nfunction fromString (string) {\n if (typeof string !== 'string') {\n throw new Error('Param is not a string')\n }\n\n const lcStr = string.toLowerCase()\n\n switch (lcStr) {\n case 'numeric':\n return exports.NUMERIC\n case 'alphanumeric':\n return exports.ALPHANUMERIC\n case 'kanji':\n return exports.KANJI\n case 'byte':\n return exports.BYTE\n default:\n throw new Error('Unknown mode: ' + string)\n }\n}\n\n/**\n * Returns mode from a value.\n * If value is not a valid mode, returns defaultValue\n *\n * @param {Mode|String} value Encoding mode\n * @param {Mode} defaultValue Fallback value\n * @return {Mode} Encoding mode\n */\nexports.from = function from (value, defaultValue) {\n if (exports.isValid(value)) {\n return value\n }\n\n try {\n return fromString(value)\n } catch (e) {\n return defaultValue\n }\n}\n", "const Utils = require('./utils')\nconst ECCode = require('./error-correction-code')\nconst ECLevel = require('./error-correction-level')\nconst Mode = require('./mode')\nconst VersionCheck = require('./version-check')\n\n// Generator polynomial used to encode version information\nconst G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0)\nconst G18_BCH = Utils.getBCHDigit(G18)\n\nfunction getBestVersionForDataLength (mode, length, errorCorrectionLevel) {\n for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {\n if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) {\n return currentVersion\n }\n }\n\n return undefined\n}\n\nfunction getReservedBitsCount (mode, version) {\n // Character count indicator + mode indicator bits\n return Mode.getCharCountIndicator(mode, version) + 4\n}\n\nfunction getTotalBitsFromDataArray (segments, version) {\n let totalBits = 0\n\n segments.forEach(function (data) {\n const reservedBits = getReservedBitsCount(data.mode, version)\n totalBits += reservedBits + data.getBitsLength()\n })\n\n return totalBits\n}\n\nfunction getBestVersionForMixedData (segments, errorCorrectionLevel) {\n for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {\n const length = getTotalBitsFromDataArray(segments, currentVersion)\n if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, Mode.MIXED)) {\n return currentVersion\n }\n }\n\n return undefined\n}\n\n/**\n * Returns version number from a value.\n * If value is not a valid version, returns defaultValue\n *\n * @param {Number|String} value QR Code version\n * @param {Number} defaultValue Fallback value\n * @return {Number} QR Code version number\n */\nexports.from = function from (value, defaultValue) {\n if (VersionCheck.isValid(value)) {\n return parseInt(value, 10)\n }\n\n return defaultValue\n}\n\n/**\n * Returns how much data can be stored with the specified QR code version\n * and error correction level\n *\n * @param {Number} version QR Code version (1-40)\n * @param {Number} errorCorrectionLevel Error correction level\n * @param {Mode} mode Data mode\n * @return {Number} Quantity of storable data\n */\nexports.getCapacity = function getCapacity (version, errorCorrectionLevel, mode) {\n if (!VersionCheck.isValid(version)) {\n throw new Error('Invalid QR Code version')\n }\n\n // Use Byte mode as default\n if (typeof mode === 'undefined') mode = Mode.BYTE\n\n // Total codewords for this QR code version (Data + Error correction)\n const totalCodewords = Utils.getSymbolTotalCodewords(version)\n\n // Total number of error correction codewords\n const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)\n\n // Total number of data codewords\n const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8\n\n if (mode === Mode.MIXED) return dataTotalCodewordsBits\n\n const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode, version)\n\n // Return max number of storable codewords\n switch (mode) {\n case Mode.NUMERIC:\n return Math.floor((usableBits / 10) * 3)\n\n case Mode.ALPHANUMERIC:\n return Math.floor((usableBits / 11) * 2)\n\n case Mode.KANJI:\n return Math.floor(usableBits / 13)\n\n case Mode.BYTE:\n default:\n return Math.floor(usableBits / 8)\n }\n}\n\n/**\n * Returns the minimum version needed to contain the amount of data\n *\n * @param {Segment} data Segment of data\n * @param {Number} [errorCorrectionLevel=H] Error correction level\n * @param {Mode} mode Data mode\n * @return {Number} QR Code version\n */\nexports.getBestVersionForData = function getBestVersionForData (data, errorCorrectionLevel) {\n let seg\n\n const ecl = ECLevel.from(errorCorrectionLevel, ECLevel.M)\n\n if (Array.isArray(data)) {\n if (data.length > 1) {\n return getBestVersionForMixedData(data, ecl)\n }\n\n if (data.length === 0) {\n return 1\n }\n\n seg = data[0]\n } else {\n seg = data\n }\n\n return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl)\n}\n\n/**\n * Returns version information with relative error correction bits\n *\n * The version information is included in QR Code symbols of version 7 or larger.\n * It consists of an 18-bit sequence containing 6 data bits,\n * with 12 error correction bits calculated using the (18, 6) Golay code.\n *\n * @param {Number} version QR Code version\n * @return {Number} Encoded version info bits\n */\nexports.getEncodedBits = function getEncodedBits (version) {\n if (!VersionCheck.isValid(version) || version < 7) {\n throw new Error('Invalid QR Code version')\n }\n\n let d = version << 12\n\n while (Utils.getBCHDigit(d) - G18_BCH >= 0) {\n d ^= (G18 << (Utils.getBCHDigit(d) - G18_BCH))\n }\n\n return (version << 12) | d\n}\n", "const Utils = require('./utils')\n\nconst G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0)\nconst G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1)\nconst G15_BCH = Utils.getBCHDigit(G15)\n\n/**\n * Returns format information with relative error correction bits\n *\n * The format information is a 15-bit sequence containing 5 data bits,\n * with 10 error correction bits calculated using the (15, 5) BCH code.\n *\n * @param {Number} errorCorrectionLevel Error correction level\n * @param {Number} mask Mask pattern\n * @return {Number} Encoded format information bits\n */\nexports.getEncodedBits = function getEncodedBits (errorCorrectionLevel, mask) {\n const data = ((errorCorrectionLevel.bit << 3) | mask)\n let d = data << 10\n\n while (Utils.getBCHDigit(d) - G15_BCH >= 0) {\n d ^= (G15 << (Utils.getBCHDigit(d) - G15_BCH))\n }\n\n // xor final data with mask pattern in order to ensure that\n // no combination of Error Correction Level and data mask pattern\n // will result in an all-zero data string\n return ((data << 10) | d) ^ G15_MASK\n}\n", "const Mode = require('./mode')\n\nfunction NumericData (data) {\n this.mode = Mode.NUMERIC\n this.data = data.toString()\n}\n\nNumericData.getBitsLength = function getBitsLength (length) {\n return 10 * Math.floor(length / 3) + ((length % 3) ? ((length % 3) * 3 + 1) : 0)\n}\n\nNumericData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nNumericData.prototype.getBitsLength = function getBitsLength () {\n return NumericData.getBitsLength(this.data.length)\n}\n\nNumericData.prototype.write = function write (bitBuffer) {\n let i, group, value\n\n // The input data string is divided into groups of three digits,\n // and each group is converted to its 10-bit binary equivalent.\n for (i = 0; i + 3 <= this.data.length; i += 3) {\n group = this.data.substr(i, 3)\n value = parseInt(group, 10)\n\n bitBuffer.put(value, 10)\n }\n\n // If the number of input digits is not an exact multiple of three,\n // the final one or two digits are converted to 4 or 7 bits respectively.\n const remainingNum = this.data.length - i\n if (remainingNum > 0) {\n group = this.data.substr(i)\n value = parseInt(group, 10)\n\n bitBuffer.put(value, remainingNum * 3 + 1)\n }\n}\n\nmodule.exports = NumericData\n", "const Mode = require('./mode')\n\n/**\n * Array of characters available in alphanumeric mode\n *\n * As per QR Code specification, to each character\n * is assigned a value from 0 to 44 which in this case coincides\n * with the array index\n *\n * @type {Array}\n */\nconst ALPHA_NUM_CHARS = [\n '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\n 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',\n 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',\n ' ', '$', '%', '*', '+', '-', '.', '/', ':'\n]\n\nfunction AlphanumericData (data) {\n this.mode = Mode.ALPHANUMERIC\n this.data = data\n}\n\nAlphanumericData.getBitsLength = function getBitsLength (length) {\n return 11 * Math.floor(length / 2) + 6 * (length % 2)\n}\n\nAlphanumericData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nAlphanumericData.prototype.getBitsLength = function getBitsLength () {\n return AlphanumericData.getBitsLength(this.data.length)\n}\n\nAlphanumericData.prototype.write = function write (bitBuffer) {\n let i\n\n // Input data characters are divided into groups of two characters\n // and encoded as 11-bit binary codes.\n for (i = 0; i + 2 <= this.data.length; i += 2) {\n // The character value of the first character is multiplied by 45\n let value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45\n\n // The character value of the second digit is added to the product\n value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1])\n\n // The sum is then stored as 11-bit binary number\n bitBuffer.put(value, 11)\n }\n\n // If the number of input data characters is not a multiple of two,\n // the character value of the final character is encoded as a 6-bit binary number.\n if (this.data.length % 2) {\n bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6)\n }\n}\n\nmodule.exports = AlphanumericData\n", "const Mode = require('./mode')\n\nfunction ByteData (data) {\n this.mode = Mode.BYTE\n if (typeof (data) === 'string') {\n this.data = new TextEncoder().encode(data)\n } else {\n this.data = new Uint8Array(data)\n }\n}\n\nByteData.getBitsLength = function getBitsLength (length) {\n return length * 8\n}\n\nByteData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nByteData.prototype.getBitsLength = function getBitsLength () {\n return ByteData.getBitsLength(this.data.length)\n}\n\nByteData.prototype.write = function (bitBuffer) {\n for (let i = 0, l = this.data.length; i < l; i++) {\n bitBuffer.put(this.data[i], 8)\n }\n}\n\nmodule.exports = ByteData\n", "const Mode = require('./mode')\nconst Utils = require('./utils')\n\nfunction KanjiData (data) {\n this.mode = Mode.KANJI\n this.data = data\n}\n\nKanjiData.getBitsLength = function getBitsLength (length) {\n return length * 13\n}\n\nKanjiData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nKanjiData.prototype.getBitsLength = function getBitsLength () {\n return KanjiData.getBitsLength(this.data.length)\n}\n\nKanjiData.prototype.write = function (bitBuffer) {\n let i\n\n // In the Shift JIS system, Kanji characters are represented by a two byte combination.\n // These byte values are shifted from the JIS X 0208 values.\n // JIS X 0208 gives details of the shift coded representation.\n for (i = 0; i < this.data.length; i++) {\n let value = Utils.toSJIS(this.data[i])\n\n // For characters with Shift JIS values from 0x8140 to 0x9FFC:\n if (value >= 0x8140 && value <= 0x9FFC) {\n // Subtract 0x8140 from Shift JIS value\n value -= 0x8140\n\n // For characters with Shift JIS values from 0xE040 to 0xEBBF\n } else if (value >= 0xE040 && value <= 0xEBBF) {\n // Subtract 0xC140 from Shift JIS value\n value -= 0xC140\n } else {\n throw new Error(\n 'Invalid SJIS character: ' + this.data[i] + '\\n' +\n 'Make sure your charset is UTF-8')\n }\n\n // Multiply most significant byte of result by 0xC0\n // and add least significant byte to product\n value = (((value >>> 8) & 0xff) * 0xC0) + (value & 0xff)\n\n // Convert result to a 13-bit binary string\n bitBuffer.put(value, 13)\n }\n}\n\nmodule.exports = KanjiData\n", "'use strict';\n\n/******************************************************************************\n * Created 2008-08-19.\n *\n * Dijkstra path-finding functions. Adapted from the Dijkstar Python project.\n *\n * Copyright (C) 2008\n * Wyatt Baldwin \n * All rights reserved\n *\n * Licensed under the MIT license.\n *\n * http://www.opensource.org/licenses/mit-license.php\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *****************************************************************************/\nvar dijkstra = {\n single_source_shortest_paths: function(graph, s, d) {\n // Predecessor map for each node that has been encountered.\n // node ID => predecessor node ID\n var predecessors = {};\n\n // Costs of shortest paths from s to all nodes encountered.\n // node ID => cost\n var costs = {};\n costs[s] = 0;\n\n // Costs of shortest paths from s to all nodes encountered; differs from\n // `costs` in that it provides easy access to the node that currently has\n // the known shortest path from s.\n // XXX: Do we actually need both `costs` and `open`?\n var open = dijkstra.PriorityQueue.make();\n open.push(s, 0);\n\n var closest,\n u, v,\n cost_of_s_to_u,\n adjacent_nodes,\n cost_of_e,\n cost_of_s_to_u_plus_cost_of_e,\n cost_of_s_to_v,\n first_visit;\n while (!open.empty()) {\n // In the nodes remaining in graph that have a known cost from s,\n // find the node, u, that currently has the shortest path from s.\n closest = open.pop();\n u = closest.value;\n cost_of_s_to_u = closest.cost;\n\n // Get nodes adjacent to u...\n adjacent_nodes = graph[u] || {};\n\n // ...and explore the edges that connect u to those nodes, updating\n // the cost of the shortest paths to any or all of those nodes as\n // necessary. v is the node across the current edge from u.\n for (v in adjacent_nodes) {\n if (adjacent_nodes.hasOwnProperty(v)) {\n // Get the cost of the edge running from u to v.\n cost_of_e = adjacent_nodes[v];\n\n // Cost of s to u plus the cost of u to v across e--this is *a*\n // cost from s to v that may or may not be less than the current\n // known cost to v.\n cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;\n\n // If we haven't visited v yet OR if the current known cost from s to\n // v is greater than the new cost we just found (cost of s to u plus\n // cost of u to v across e), update v's cost in the cost list and\n // update v's predecessor in the predecessor list (it's now u).\n cost_of_s_to_v = costs[v];\n first_visit = (typeof costs[v] === 'undefined');\n if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {\n costs[v] = cost_of_s_to_u_plus_cost_of_e;\n open.push(v, cost_of_s_to_u_plus_cost_of_e);\n predecessors[v] = u;\n }\n }\n }\n }\n\n if (typeof d !== 'undefined' && typeof costs[d] === 'undefined') {\n var msg = ['Could not find a path from ', s, ' to ', d, '.'].join('');\n throw new Error(msg);\n }\n\n return predecessors;\n },\n\n extract_shortest_path_from_predecessor_list: function(predecessors, d) {\n var nodes = [];\n var u = d;\n var predecessor;\n while (u) {\n nodes.push(u);\n predecessor = predecessors[u];\n u = predecessors[u];\n }\n nodes.reverse();\n return nodes;\n },\n\n find_path: function(graph, s, d) {\n var predecessors = dijkstra.single_source_shortest_paths(graph, s, d);\n return dijkstra.extract_shortest_path_from_predecessor_list(\n predecessors, d);\n },\n\n /**\n * A very naive priority queue implementation.\n */\n PriorityQueue: {\n make: function (opts) {\n var T = dijkstra.PriorityQueue,\n t = {},\n key;\n opts = opts || {};\n for (key in T) {\n if (T.hasOwnProperty(key)) {\n t[key] = T[key];\n }\n }\n t.queue = [];\n t.sorter = opts.sorter || T.default_sorter;\n return t;\n },\n\n default_sorter: function (a, b) {\n return a.cost - b.cost;\n },\n\n /**\n * Add a new item to the queue and ensure the highest priority element\n * is at the front of the queue.\n */\n push: function (value, cost) {\n var item = {value: value, cost: cost};\n this.queue.push(item);\n this.queue.sort(this.sorter);\n },\n\n /**\n * Return the highest priority element in the queue.\n */\n pop: function () {\n return this.queue.shift();\n },\n\n empty: function () {\n return this.queue.length === 0;\n }\n }\n};\n\n\n// node.js module exports\nif (typeof module !== 'undefined') {\n module.exports = dijkstra;\n}\n", "const Mode = require('./mode')\nconst NumericData = require('./numeric-data')\nconst AlphanumericData = require('./alphanumeric-data')\nconst ByteData = require('./byte-data')\nconst KanjiData = require('./kanji-data')\nconst Regex = require('./regex')\nconst Utils = require('./utils')\nconst dijkstra = require('dijkstrajs')\n\n/**\n * Returns UTF8 byte length\n *\n * @param {String} str Input string\n * @return {Number} Number of byte\n */\nfunction getStringByteLength (str) {\n return unescape(encodeURIComponent(str)).length\n}\n\n/**\n * Get a list of segments of the specified mode\n * from a string\n *\n * @param {Mode} mode Segment mode\n * @param {String} str String to process\n * @return {Array} Array of object with segments data\n */\nfunction getSegments (regex, mode, str) {\n const segments = []\n let result\n\n while ((result = regex.exec(str)) !== null) {\n segments.push({\n data: result[0],\n index: result.index,\n mode: mode,\n length: result[0].length\n })\n }\n\n return segments\n}\n\n/**\n * Extracts a series of segments with the appropriate\n * modes from a string\n *\n * @param {String} dataStr Input string\n * @return {Array} Array of object with segments data\n */\nfunction getSegmentsFromString (dataStr) {\n const numSegs = getSegments(Regex.NUMERIC, Mode.NUMERIC, dataStr)\n const alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode.ALPHANUMERIC, dataStr)\n let byteSegs\n let kanjiSegs\n\n if (Utils.isKanjiModeEnabled()) {\n byteSegs = getSegments(Regex.BYTE, Mode.BYTE, dataStr)\n kanjiSegs = getSegments(Regex.KANJI, Mode.KANJI, dataStr)\n } else {\n byteSegs = getSegments(Regex.BYTE_KANJI, Mode.BYTE, dataStr)\n kanjiSegs = []\n }\n\n const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs)\n\n return segs\n .sort(function (s1, s2) {\n return s1.index - s2.index\n })\n .map(function (obj) {\n return {\n data: obj.data,\n mode: obj.mode,\n length: obj.length\n }\n })\n}\n\n/**\n * Returns how many bits are needed to encode a string of\n * specified length with the specified mode\n *\n * @param {Number} length String length\n * @param {Mode} mode Segment mode\n * @return {Number} Bit length\n */\nfunction getSegmentBitsLength (length, mode) {\n switch (mode) {\n case Mode.NUMERIC:\n return NumericData.getBitsLength(length)\n case Mode.ALPHANUMERIC:\n return AlphanumericData.getBitsLength(length)\n case Mode.KANJI:\n return KanjiData.getBitsLength(length)\n case Mode.BYTE:\n return ByteData.getBitsLength(length)\n }\n}\n\n/**\n * Merges adjacent segments which have the same mode\n *\n * @param {Array} segs Array of object with segments data\n * @return {Array} Array of object with segments data\n */\nfunction mergeSegments (segs) {\n return segs.reduce(function (acc, curr) {\n const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null\n if (prevSeg && prevSeg.mode === curr.mode) {\n acc[acc.length - 1].data += curr.data\n return acc\n }\n\n acc.push(curr)\n return acc\n }, [])\n}\n\n/**\n * Generates a list of all possible nodes combination which\n * will be used to build a segments graph.\n *\n * Nodes are divided by groups. Each group will contain a list of all the modes\n * in which is possible to encode the given text.\n *\n * For example the text '12345' can be encoded as Numeric, Alphanumeric or Byte.\n * The group for '12345' will contain then 3 objects, one for each\n * possible encoding mode.\n *\n * Each node represents a possible segment.\n *\n * @param {Array} segs Array of object with segments data\n * @return {Array} Array of object with segments data\n */\nfunction buildNodes (segs) {\n const nodes = []\n for (let i = 0; i < segs.length; i++) {\n const seg = segs[i]\n\n switch (seg.mode) {\n case Mode.NUMERIC:\n nodes.push([seg,\n { data: seg.data, mode: Mode.ALPHANUMERIC, length: seg.length },\n { data: seg.data, mode: Mode.BYTE, length: seg.length }\n ])\n break\n case Mode.ALPHANUMERIC:\n nodes.push([seg,\n { data: seg.data, mode: Mode.BYTE, length: seg.length }\n ])\n break\n case Mode.KANJI:\n nodes.push([seg,\n { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }\n ])\n break\n case Mode.BYTE:\n nodes.push([\n { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }\n ])\n }\n }\n\n return nodes\n}\n\n/**\n * Builds a graph from a list of nodes.\n * All segments in each node group will be connected with all the segments of\n * the next group and so on.\n *\n * At each connection will be assigned a weight depending on the\n * segment's byte length.\n *\n * @param {Array} nodes Array of object with segments data\n * @param {Number} version QR Code version\n * @return {Object} Graph of all possible segments\n */\nfunction buildGraph (nodes, version) {\n const table = {}\n const graph = { start: {} }\n let prevNodeIds = ['start']\n\n for (let i = 0; i < nodes.length; i++) {\n const nodeGroup = nodes[i]\n const currentNodeIds = []\n\n for (let j = 0; j < nodeGroup.length; j++) {\n const node = nodeGroup[j]\n const key = '' + i + j\n\n currentNodeIds.push(key)\n table[key] = { node: node, lastCount: 0 }\n graph[key] = {}\n\n for (let n = 0; n < prevNodeIds.length; n++) {\n const prevNodeId = prevNodeIds[n]\n\n if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) {\n graph[prevNodeId][key] =\n getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) -\n getSegmentBitsLength(table[prevNodeId].lastCount, node.mode)\n\n table[prevNodeId].lastCount += node.length\n } else {\n if (table[prevNodeId]) table[prevNodeId].lastCount = node.length\n\n graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) +\n 4 + Mode.getCharCountIndicator(node.mode, version) // switch cost\n }\n }\n }\n\n prevNodeIds = currentNodeIds\n }\n\n for (let n = 0; n < prevNodeIds.length; n++) {\n graph[prevNodeIds[n]].end = 0\n }\n\n return { map: graph, table: table }\n}\n\n/**\n * Builds a segment from a specified data and mode.\n * If a mode is not specified, the more suitable will be used.\n *\n * @param {String} data Input data\n * @param {Mode | String} modesHint Data mode\n * @return {Segment} Segment\n */\nfunction buildSingleSegment (data, modesHint) {\n let mode\n const bestMode = Mode.getBestModeForData(data)\n\n mode = Mode.from(modesHint, bestMode)\n\n // Make sure data can be encoded\n if (mode !== Mode.BYTE && mode.bit < bestMode.bit) {\n throw new Error('\"' + data + '\"' +\n ' cannot be encoded with mode ' + Mode.toString(mode) +\n '.\\n Suggested mode is: ' + Mode.toString(bestMode))\n }\n\n // Use Mode.BYTE if Kanji support is disabled\n if (mode === Mode.KANJI && !Utils.isKanjiModeEnabled()) {\n mode = Mode.BYTE\n }\n\n switch (mode) {\n case Mode.NUMERIC:\n return new NumericData(data)\n\n case Mode.ALPHANUMERIC:\n return new AlphanumericData(data)\n\n case Mode.KANJI:\n return new KanjiData(data)\n\n case Mode.BYTE:\n return new ByteData(data)\n }\n}\n\n/**\n * Builds a list of segments from an array.\n * Array can contain Strings or Objects with segment's info.\n *\n * For each item which is a string, will be generated a segment with the given\n * string and the more appropriate encoding mode.\n *\n * For each item which is an object, will be generated a segment with the given\n * data and mode.\n * Objects must contain at least the property \"data\".\n * If property \"mode\" is not present, the more suitable mode will be used.\n *\n * @param {Array} array Array of objects with segments data\n * @return {Array} Array of Segments\n */\nexports.fromArray = function fromArray (array) {\n return array.reduce(function (acc, seg) {\n if (typeof seg === 'string') {\n acc.push(buildSingleSegment(seg, null))\n } else if (seg.data) {\n acc.push(buildSingleSegment(seg.data, seg.mode))\n }\n\n return acc\n }, [])\n}\n\n/**\n * Builds an optimized sequence of segments from a string,\n * which will produce the shortest possible bitstream.\n *\n * @param {String} data Input string\n * @param {Number} version QR Code version\n * @return {Array} Array of segments\n */\nexports.fromString = function fromString (data, version) {\n const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled())\n\n const nodes = buildNodes(segs)\n const graph = buildGraph(nodes, version)\n const path = dijkstra.find_path(graph.map, 'start', 'end')\n\n const optimizedSegs = []\n for (let i = 1; i < path.length - 1; i++) {\n optimizedSegs.push(graph.table[path[i]].node)\n }\n\n return exports.fromArray(mergeSegments(optimizedSegs))\n}\n\n/**\n * Splits a string in various segments with the modes which\n * best represent their content.\n * The produced segments are far from being optimized.\n * The output of this function is only used to estimate a QR Code version\n * which may contain the data.\n *\n * @param {string} data Input string\n * @return {Array} Array of segments\n */\nexports.rawSplit = function rawSplit (data) {\n return exports.fromArray(\n getSegmentsFromString(data, Utils.isKanjiModeEnabled())\n )\n}\n", "const Utils = require('./utils')\nconst ECLevel = require('./error-correction-level')\nconst BitBuffer = require('./bit-buffer')\nconst BitMatrix = require('./bit-matrix')\nconst AlignmentPattern = require('./alignment-pattern')\nconst FinderPattern = require('./finder-pattern')\nconst MaskPattern = require('./mask-pattern')\nconst ECCode = require('./error-correction-code')\nconst ReedSolomonEncoder = require('./reed-solomon-encoder')\nconst Version = require('./version')\nconst FormatInfo = require('./format-info')\nconst Mode = require('./mode')\nconst Segments = require('./segments')\n\n/**\n * QRCode for JavaScript\n *\n * modified by Ryan Day for nodejs support\n * Copyright (c) 2011 Ryan Day\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/mit-license.php\n *\n//---------------------------------------------------------------------\n// QRCode for JavaScript\n//\n// Copyright (c) 2009 Kazuhiko Arase\n//\n// URL: http://www.d-project.com/\n//\n// Licensed under the MIT license:\n// http://www.opensource.org/licenses/mit-license.php\n//\n// The word \"QR Code\" is registered trademark of\n// DENSO WAVE INCORPORATED\n// http://www.denso-wave.com/qrcode/faqpatent-e.html\n//\n//---------------------------------------------------------------------\n*/\n\n/**\n * Add finder patterns bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupFinderPattern (matrix, version) {\n const size = matrix.size\n const pos = FinderPattern.getPositions(version)\n\n for (let i = 0; i < pos.length; i++) {\n const row = pos[i][0]\n const col = pos[i][1]\n\n for (let r = -1; r <= 7; r++) {\n if (row + r <= -1 || size <= row + r) continue\n\n for (let c = -1; c <= 7; c++) {\n if (col + c <= -1 || size <= col + c) continue\n\n if ((r >= 0 && r <= 6 && (c === 0 || c === 6)) ||\n (c >= 0 && c <= 6 && (r === 0 || r === 6)) ||\n (r >= 2 && r <= 4 && c >= 2 && c <= 4)) {\n matrix.set(row + r, col + c, true, true)\n } else {\n matrix.set(row + r, col + c, false, true)\n }\n }\n }\n }\n}\n\n/**\n * Add timing pattern bits to matrix\n *\n * Note: this function must be called before {@link setupAlignmentPattern}\n *\n * @param {BitMatrix} matrix Modules matrix\n */\nfunction setupTimingPattern (matrix) {\n const size = matrix.size\n\n for (let r = 8; r < size - 8; r++) {\n const value = r % 2 === 0\n matrix.set(r, 6, value, true)\n matrix.set(6, r, value, true)\n }\n}\n\n/**\n * Add alignment patterns bits to matrix\n *\n * Note: this function must be called after {@link setupTimingPattern}\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupAlignmentPattern (matrix, version) {\n const pos = AlignmentPattern.getPositions(version)\n\n for (let i = 0; i < pos.length; i++) {\n const row = pos[i][0]\n const col = pos[i][1]\n\n for (let r = -2; r <= 2; r++) {\n for (let c = -2; c <= 2; c++) {\n if (r === -2 || r === 2 || c === -2 || c === 2 ||\n (r === 0 && c === 0)) {\n matrix.set(row + r, col + c, true, true)\n } else {\n matrix.set(row + r, col + c, false, true)\n }\n }\n }\n }\n}\n\n/**\n * Add version info bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupVersionInfo (matrix, version) {\n const size = matrix.size\n const bits = Version.getEncodedBits(version)\n let row, col, mod\n\n for (let i = 0; i < 18; i++) {\n row = Math.floor(i / 3)\n col = i % 3 + size - 8 - 3\n mod = ((bits >> i) & 1) === 1\n\n matrix.set(row, col, mod, true)\n matrix.set(col, row, mod, true)\n }\n}\n\n/**\n * Add format info bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @param {Number} maskPattern Mask pattern reference value\n */\nfunction setupFormatInfo (matrix, errorCorrectionLevel, maskPattern) {\n const size = matrix.size\n const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern)\n let i, mod\n\n for (i = 0; i < 15; i++) {\n mod = ((bits >> i) & 1) === 1\n\n // vertical\n if (i < 6) {\n matrix.set(i, 8, mod, true)\n } else if (i < 8) {\n matrix.set(i + 1, 8, mod, true)\n } else {\n matrix.set(size - 15 + i, 8, mod, true)\n }\n\n // horizontal\n if (i < 8) {\n matrix.set(8, size - i - 1, mod, true)\n } else if (i < 9) {\n matrix.set(8, 15 - i - 1 + 1, mod, true)\n } else {\n matrix.set(8, 15 - i - 1, mod, true)\n }\n }\n\n // fixed module\n matrix.set(size - 8, 8, 1, true)\n}\n\n/**\n * Add encoded data bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Uint8Array} data Data codewords\n */\nfunction setupData (matrix, data) {\n const size = matrix.size\n let inc = -1\n let row = size - 1\n let bitIndex = 7\n let byteIndex = 0\n\n for (let col = size - 1; col > 0; col -= 2) {\n if (col === 6) col--\n\n while (true) {\n for (let c = 0; c < 2; c++) {\n if (!matrix.isReserved(row, col - c)) {\n let dark = false\n\n if (byteIndex < data.length) {\n dark = (((data[byteIndex] >>> bitIndex) & 1) === 1)\n }\n\n matrix.set(row, col - c, dark)\n bitIndex--\n\n if (bitIndex === -1) {\n byteIndex++\n bitIndex = 7\n }\n }\n }\n\n row += inc\n\n if (row < 0 || size <= row) {\n row -= inc\n inc = -inc\n break\n }\n }\n }\n}\n\n/**\n * Create encoded codewords from data input\n *\n * @param {Number} version QR Code version\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @param {ByteData} data Data input\n * @return {Uint8Array} Buffer containing encoded codewords\n */\nfunction createData (version, errorCorrectionLevel, segments) {\n // Prepare data buffer\n const buffer = new BitBuffer()\n\n segments.forEach(function (data) {\n // prefix data with mode indicator (4 bits)\n buffer.put(data.mode.bit, 4)\n\n // Prefix data with character count indicator.\n // The character count indicator is a string of bits that represents the\n // number of characters that are being encoded.\n // The character count indicator must be placed after the mode indicator\n // and must be a certain number of bits long, depending on the QR version\n // and data mode\n // @see {@link Mode.getCharCountIndicator}.\n buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version))\n\n // add binary data sequence to buffer\n data.write(buffer)\n })\n\n // Calculate required number of bits\n const totalCodewords = Utils.getSymbolTotalCodewords(version)\n const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)\n const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8\n\n // Add a terminator.\n // If the bit string is shorter than the total number of required bits,\n // a terminator of up to four 0s must be added to the right side of the string.\n // If the bit string is more than four bits shorter than the required number of bits,\n // add four 0s to the end.\n if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) {\n buffer.put(0, 4)\n }\n\n // If the bit string is fewer than four bits shorter, add only the number of 0s that\n // are needed to reach the required number of bits.\n\n // After adding the terminator, if the number of bits in the string is not a multiple of 8,\n // pad the string on the right with 0s to make the string's length a multiple of 8.\n while (buffer.getLengthInBits() % 8 !== 0) {\n buffer.putBit(0)\n }\n\n // Add pad bytes if the string is still shorter than the total number of required bits.\n // Extend the buffer to fill the data capacity of the symbol corresponding to\n // the Version and Error Correction Level by adding the Pad Codewords 11101100 (0xEC)\n // and 00010001 (0x11) alternately.\n const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8\n for (let i = 0; i < remainingByte; i++) {\n buffer.put(i % 2 ? 0x11 : 0xEC, 8)\n }\n\n return createCodewords(buffer, version, errorCorrectionLevel)\n}\n\n/**\n * Encode input data with Reed-Solomon and return codewords with\n * relative error correction bits\n *\n * @param {BitBuffer} bitBuffer Data to encode\n * @param {Number} version QR Code version\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @return {Uint8Array} Buffer containing encoded codewords\n */\nfunction createCodewords (bitBuffer, version, errorCorrectionLevel) {\n // Total codewords for this QR code version (Data + Error correction)\n const totalCodewords = Utils.getSymbolTotalCodewords(version)\n\n // Total number of error correction codewords\n const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)\n\n // Total number of data codewords\n const dataTotalCodewords = totalCodewords - ecTotalCodewords\n\n // Total number of blocks\n const ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel)\n\n // Calculate how many blocks each group should contain\n const blocksInGroup2 = totalCodewords % ecTotalBlocks\n const blocksInGroup1 = ecTotalBlocks - blocksInGroup2\n\n const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks)\n\n const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks)\n const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1\n\n // Number of EC codewords is the same for both groups\n const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1\n\n // Initialize a Reed-Solomon encoder with a generator polynomial of degree ecCount\n const rs = new ReedSolomonEncoder(ecCount)\n\n let offset = 0\n const dcData = new Array(ecTotalBlocks)\n const ecData = new Array(ecTotalBlocks)\n let maxDataSize = 0\n const buffer = new Uint8Array(bitBuffer.buffer)\n\n // Divide the buffer into the required number of blocks\n for (let b = 0; b < ecTotalBlocks; b++) {\n const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2\n\n // extract a block of data from buffer\n dcData[b] = buffer.slice(offset, offset + dataSize)\n\n // Calculate EC codewords for this data block\n ecData[b] = rs.encode(dcData[b])\n\n offset += dataSize\n maxDataSize = Math.max(maxDataSize, dataSize)\n }\n\n // Create final data\n // Interleave the data and error correction codewords from each block\n const data = new Uint8Array(totalCodewords)\n let index = 0\n let i, r\n\n // Add data codewords\n for (i = 0; i < maxDataSize; i++) {\n for (r = 0; r < ecTotalBlocks; r++) {\n if (i < dcData[r].length) {\n data[index++] = dcData[r][i]\n }\n }\n }\n\n // Apped EC codewords\n for (i = 0; i < ecCount; i++) {\n for (r = 0; r < ecTotalBlocks; r++) {\n data[index++] = ecData[r][i]\n }\n }\n\n return data\n}\n\n/**\n * Build QR Code symbol\n *\n * @param {String} data Input string\n * @param {Number} version QR Code version\n * @param {ErrorCorretionLevel} errorCorrectionLevel Error level\n * @param {MaskPattern} maskPattern Mask pattern\n * @return {Object} Object containing symbol data\n */\nfunction createSymbol (data, version, errorCorrectionLevel, maskPattern) {\n let segments\n\n if (Array.isArray(data)) {\n segments = Segments.fromArray(data)\n } else if (typeof data === 'string') {\n let estimatedVersion = version\n\n if (!estimatedVersion) {\n const rawSegments = Segments.rawSplit(data)\n\n // Estimate best version that can contain raw splitted segments\n estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel)\n }\n\n // Build optimized segments\n // If estimated version is undefined, try with the highest version\n segments = Segments.fromString(data, estimatedVersion || 40)\n } else {\n throw new Error('Invalid data')\n }\n\n // Get the min version that can contain data\n const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel)\n\n // If no version is found, data cannot be stored\n if (!bestVersion) {\n throw new Error('The amount of data is too big to be stored in a QR Code')\n }\n\n // If not specified, use min version as default\n if (!version) {\n version = bestVersion\n\n // Check if the specified version can contain the data\n } else if (version < bestVersion) {\n throw new Error('\\n' +\n 'The chosen QR Code version cannot contain this amount of data.\\n' +\n 'Minimum version required to store current data is: ' + bestVersion + '.\\n'\n )\n }\n\n const dataBits = createData(version, errorCorrectionLevel, segments)\n\n // Allocate matrix buffer\n const moduleCount = Utils.getSymbolSize(version)\n const modules = new BitMatrix(moduleCount)\n\n // Add function modules\n setupFinderPattern(modules, version)\n setupTimingPattern(modules)\n setupAlignmentPattern(modules, version)\n\n // Add temporary dummy bits for format info just to set them as reserved.\n // This is needed to prevent these bits from being masked by {@link MaskPattern.applyMask}\n // since the masking operation must be performed only on the encoding region.\n // These blocks will be replaced with correct values later in code.\n setupFormatInfo(modules, errorCorrectionLevel, 0)\n\n if (version >= 7) {\n setupVersionInfo(modules, version)\n }\n\n // Add data codewords\n setupData(modules, dataBits)\n\n if (isNaN(maskPattern)) {\n // Find best mask pattern\n maskPattern = MaskPattern.getBestMask(modules,\n setupFormatInfo.bind(null, modules, errorCorrectionLevel))\n }\n\n // Apply mask pattern\n MaskPattern.applyMask(maskPattern, modules)\n\n // Replace format info bits with correct values\n setupFormatInfo(modules, errorCorrectionLevel, maskPattern)\n\n return {\n modules: modules,\n version: version,\n errorCorrectionLevel: errorCorrectionLevel,\n maskPattern: maskPattern,\n segments: segments\n }\n}\n\n/**\n * QR Code\n *\n * @param {String | Array} data Input data\n * @param {Object} options Optional configurations\n * @param {Number} options.version QR Code version\n * @param {String} options.errorCorrectionLevel Error correction level\n * @param {Function} options.toSJISFunc Helper func to convert utf8 to sjis\n */\nexports.create = function create (data, options) {\n if (typeof data === 'undefined' || data === '') {\n throw new Error('No input text')\n }\n\n let errorCorrectionLevel = ECLevel.M\n let version\n let mask\n\n if (typeof options !== 'undefined') {\n // Use higher error correction level as default\n errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M)\n version = Version.from(options.version)\n mask = MaskPattern.from(options.maskPattern)\n\n if (options.toSJISFunc) {\n Utils.setToSJISFunction(options.toSJISFunc)\n }\n }\n\n return createSymbol(data, version, errorCorrectionLevel, mask)\n}\n", "function hex2rgba (hex) {\n if (typeof hex === 'number') {\n hex = hex.toString()\n }\n\n if (typeof hex !== 'string') {\n throw new Error('Color should be defined as hex string')\n }\n\n let hexCode = hex.slice().replace('#', '').split('')\n if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) {\n throw new Error('Invalid hex color: ' + hex)\n }\n\n // Convert from short to long form (fff -> ffffff)\n if (hexCode.length === 3 || hexCode.length === 4) {\n hexCode = Array.prototype.concat.apply([], hexCode.map(function (c) {\n return [c, c]\n }))\n }\n\n // Add default alpha value\n if (hexCode.length === 6) hexCode.push('F', 'F')\n\n const hexValue = parseInt(hexCode.join(''), 16)\n\n return {\n r: (hexValue >> 24) & 255,\n g: (hexValue >> 16) & 255,\n b: (hexValue >> 8) & 255,\n a: hexValue & 255,\n hex: '#' + hexCode.slice(0, 6).join('')\n }\n}\n\nexports.getOptions = function getOptions (options) {\n if (!options) options = {}\n if (!options.color) options.color = {}\n\n const margin = typeof options.margin === 'undefined' ||\n options.margin === null ||\n options.margin < 0\n ? 4\n : options.margin\n\n const width = options.width && options.width >= 21 ? options.width : undefined\n const scale = options.scale || 4\n\n return {\n width: width,\n scale: width ? 4 : scale,\n margin: margin,\n color: {\n dark: hex2rgba(options.color.dark || '#000000ff'),\n light: hex2rgba(options.color.light || '#ffffffff')\n },\n type: options.type,\n rendererOpts: options.rendererOpts || {}\n }\n}\n\nexports.getScale = function getScale (qrSize, opts) {\n return opts.width && opts.width >= qrSize + opts.margin * 2\n ? opts.width / (qrSize + opts.margin * 2)\n : opts.scale\n}\n\nexports.getImageWidth = function getImageWidth (qrSize, opts) {\n const scale = exports.getScale(qrSize, opts)\n return Math.floor((qrSize + opts.margin * 2) * scale)\n}\n\nexports.qrToImageData = function qrToImageData (imgData, qr, opts) {\n const size = qr.modules.size\n const data = qr.modules.data\n const scale = exports.getScale(size, opts)\n const symbolSize = Math.floor((size + opts.margin * 2) * scale)\n const scaledMargin = opts.margin * scale\n const palette = [opts.color.light, opts.color.dark]\n\n for (let i = 0; i < symbolSize; i++) {\n for (let j = 0; j < symbolSize; j++) {\n let posDst = (i * symbolSize + j) * 4\n let pxColor = opts.color.light\n\n if (i >= scaledMargin && j >= scaledMargin &&\n i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) {\n const iSrc = Math.floor((i - scaledMargin) / scale)\n const jSrc = Math.floor((j - scaledMargin) / scale)\n pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0]\n }\n\n imgData[posDst++] = pxColor.r\n imgData[posDst++] = pxColor.g\n imgData[posDst++] = pxColor.b\n imgData[posDst] = pxColor.a\n }\n }\n}\n", "const Utils = require('./utils')\n\nfunction clearCanvas (ctx, canvas, size) {\n ctx.clearRect(0, 0, canvas.width, canvas.height)\n\n if (!canvas.style) canvas.style = {}\n canvas.height = size\n canvas.width = size\n canvas.style.height = size + 'px'\n canvas.style.width = size + 'px'\n}\n\nfunction getCanvasElement () {\n try {\n return document.createElement('canvas')\n } catch (e) {\n throw new Error('You need to specify a canvas element')\n }\n}\n\nexports.render = function render (qrData, canvas, options) {\n let opts = options\n let canvasEl = canvas\n\n if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {\n opts = canvas\n canvas = undefined\n }\n\n if (!canvas) {\n canvasEl = getCanvasElement()\n }\n\n opts = Utils.getOptions(opts)\n const size = Utils.getImageWidth(qrData.modules.size, opts)\n\n const ctx = canvasEl.getContext('2d')\n const image = ctx.createImageData(size, size)\n Utils.qrToImageData(image.data, qrData, opts)\n\n clearCanvas(ctx, canvasEl, size)\n ctx.putImageData(image, 0, 0)\n\n return canvasEl\n}\n\nexports.renderToDataURL = function renderToDataURL (qrData, canvas, options) {\n let opts = options\n\n if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {\n opts = canvas\n canvas = undefined\n }\n\n if (!opts) opts = {}\n\n const canvasEl = exports.render(qrData, canvas, opts)\n\n const type = opts.type || 'image/png'\n const rendererOpts = opts.rendererOpts || {}\n\n return canvasEl.toDataURL(type, rendererOpts.quality)\n}\n", "const Utils = require('./utils')\n\nfunction getColorAttrib (color, attrib) {\n const alpha = color.a / 255\n const str = attrib + '=\"' + color.hex + '\"'\n\n return alpha < 1\n ? str + ' ' + attrib + '-opacity=\"' + alpha.toFixed(2).slice(1) + '\"'\n : str\n}\n\nfunction svgCmd (cmd, x, y) {\n let str = cmd + x\n if (typeof y !== 'undefined') str += ' ' + y\n\n return str\n}\n\nfunction qrToPath (data, size, margin) {\n let path = ''\n let moveBy = 0\n let newRow = false\n let lineLength = 0\n\n for (let i = 0; i < data.length; i++) {\n const col = Math.floor(i % size)\n const row = Math.floor(i / size)\n\n if (!col && !newRow) newRow = true\n\n if (data[i]) {\n lineLength++\n\n if (!(i > 0 && col > 0 && data[i - 1])) {\n path += newRow\n ? svgCmd('M', col + margin, 0.5 + row + margin)\n : svgCmd('m', moveBy, 0)\n\n moveBy = 0\n newRow = false\n }\n\n if (!(col + 1 < size && data[i + 1])) {\n path += svgCmd('h', lineLength)\n lineLength = 0\n }\n } else {\n moveBy++\n }\n }\n\n return path\n}\n\nexports.render = function render (qrData, options, cb) {\n const opts = Utils.getOptions(options)\n const size = qrData.modules.size\n const data = qrData.modules.data\n const qrcodesize = size + opts.margin * 2\n\n const bg = !opts.color.light.a\n ? ''\n : ''\n\n const path =\n ''\n\n const viewBox = 'viewBox=\"' + '0 0 ' + qrcodesize + ' ' + qrcodesize + '\"'\n\n const width = !opts.width ? '' : 'width=\"' + opts.width + '\" height=\"' + opts.width + '\" '\n\n const svgTag = '' + bg + path + '\\n'\n\n if (typeof cb === 'function') {\n cb(null, svgTag)\n }\n\n return svgTag\n}\n", "\nconst canPromise = require('./can-promise')\n\nconst QRCode = require('./core/qrcode')\nconst CanvasRenderer = require('./renderer/canvas')\nconst SvgRenderer = require('./renderer/svg-tag.js')\n\nfunction renderCanvas (renderFunc, canvas, text, opts, cb) {\n const args = [].slice.call(arguments, 1)\n const argsNum = args.length\n const isLastArgCb = typeof args[argsNum - 1] === 'function'\n\n if (!isLastArgCb && !canPromise()) {\n throw new Error('Callback required as last argument')\n }\n\n if (isLastArgCb) {\n if (argsNum < 2) {\n throw new Error('Too few arguments provided')\n }\n\n if (argsNum === 2) {\n cb = text\n text = canvas\n canvas = opts = undefined\n } else if (argsNum === 3) {\n if (canvas.getContext && typeof cb === 'undefined') {\n cb = opts\n opts = undefined\n } else {\n cb = opts\n opts = text\n text = canvas\n canvas = undefined\n }\n }\n } else {\n if (argsNum < 1) {\n throw new Error('Too few arguments provided')\n }\n\n if (argsNum === 1) {\n text = canvas\n canvas = opts = undefined\n } else if (argsNum === 2 && !canvas.getContext) {\n opts = text\n text = canvas\n canvas = undefined\n }\n\n return new Promise(function (resolve, reject) {\n try {\n const data = QRCode.create(text, opts)\n resolve(renderFunc(data, canvas, opts))\n } catch (e) {\n reject(e)\n }\n })\n }\n\n try {\n const data = QRCode.create(text, opts)\n cb(null, renderFunc(data, canvas, opts))\n } catch (e) {\n cb(e)\n }\n}\n\nexports.create = QRCode.create\nexports.toCanvas = renderCanvas.bind(null, CanvasRenderer.render)\nexports.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL)\n\n// only svg for now.\nexports.toString = renderCanvas.bind(null, function (data, _, opts) {\n return SvgRenderer.render(data, opts)\n})\n", "// Local QR generator adapter (no external CDNs)\r\n// Exposes: window.generateQRCode(text, { size?: number, margin?: number, errorCorrectionLevel?: 'L'|'M'|'Q'|'H' })\r\n\r\nimport * as QRCode from 'qrcode';\r\n\r\nasync function generateQRCode(text, opts = {}) {\r\n const size = opts.size || 300;\r\n const margin = opts.margin ?? 2;\r\n const errorCorrectionLevel = opts.errorCorrectionLevel || 'M';\r\n return await QRCode.toDataURL(text, { width: size, margin, errorCorrectionLevel });\r\n}\r\n\r\nwindow.generateQRCode = generateQRCode;\r\n"], + "mappings": "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AAI;AAAA,MAAI;AAAA,MAAI;AAAA,MACZ;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MACZ;AAAA,MAAI;AAAA,MAAI;AAAA,MAAK;AAAA,MACb;AAAA,MAAI;AAAA,MAAI;AAAA,MAAK;AAAA,MACb;AAAA,MAAI;AAAA,MAAK;AAAA,MAAK;AAAA,MACd;AAAA,MAAI;AAAA,MAAK;AAAA,MAAK;AAAA,MACd;AAAA,MAAI;AAAA,MAAK;AAAA,MAAK;AAAA,MACd;AAAA,MAAI;AAAA,MAAK;AAAA,MAAK;AAAA,MACd;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MACf;AAAA,MAAK;AAAA,MAAK;AAAA,MAAM;AAAA,MAChB;AAAA,MAAK;AAAA,MAAK;AAAA,MAAM;AAAA,MAChB;AAAA,MAAK;AAAA,MAAK;AAAA,MAAM;AAAA,MAChB;AAAA,MAAK;AAAA,MAAK;AAAA,MAAM;AAAA,MAChB;AAAA,MAAK;AAAA,MAAK;AAAA,MAAM;AAAA,MAChB;AAAA,MAAK;AAAA,MAAK;AAAA,MAAM;AAAA,MAChB;AAAA,MAAK;AAAA,MAAK;AAAA,MAAM;AAAA,MAChB;AAAA,MAAK;AAAA,MAAM;AAAA,MAAM;AAAA,MACjB;AAAA,MAAK;AAAA,MAAM;AAAA,MAAM;AAAA,MACjB;AAAA,MAAK;AAAA,MAAM;AAAA,MAAM;AAAA,MACjB;AAAA,MAAK;AAAA,MAAM;AAAA,MAAM;AAAA,MACjB;AAAA,MAAK;AAAA,MAAM;AAAA,MAAM;AAAA,MACjB;AAAA,MAAK;AAAA,MAAM;AAAA,MAAM;AAAA,MACjB;AAAA,MAAK;AAAA,MAAM;AAAA,MAAM;AAAA,IACnB;AAUA,YAAQ,iBAAiB,SAAS,eAAgB,SAAS,sBAAsB;AAC/E,cAAQ,sBAAsB;AAAA,QAC5B,KAAK,QAAQ;AACX,iBAAO,iBAAiB,UAAU,KAAK,IAAI,CAAC;AAAA,QAC9C,KAAK,QAAQ;AACX,iBAAO,iBAAiB,UAAU,KAAK,IAAI,CAAC;AAAA,QAC9C,KAAK,QAAQ;AACX,iBAAO,iBAAiB,UAAU,KAAK,IAAI,CAAC;AAAA,QAC9C,KAAK,QAAQ;AACX,iBAAO,iBAAiB,UAAU,KAAK,IAAI,CAAC;AAAA,QAC9C;AACE,iBAAO;AAAA,MACX;AAAA,IACF;AAUA,YAAQ,yBAAyB,SAAS,uBAAwB,SAAS,sBAAsB;AAC/F,cAAQ,sBAAsB;AAAA,QAC5B,KAAK,QAAQ;AACX,iBAAO,oBAAoB,UAAU,KAAK,IAAI,CAAC;AAAA,QACjD,KAAK,QAAQ;AACX,iBAAO,oBAAoB,UAAU,KAAK,IAAI,CAAC;AAAA,QACjD,KAAK,QAAQ;AACX,iBAAO,oBAAoB,UAAU,KAAK,IAAI,CAAC;AAAA,QACjD,KAAK,QAAQ;AACX,iBAAO,oBAAoB,UAAU,KAAK,IAAI,CAAC;AAAA,QACjD;AACE,iBAAO;AAAA,MACX;AAAA,IACF;AAAA;AAAA;;;ACtIA;AAAA;AAAA,QAAM,YAAY,IAAI,WAAW,GAAG;AACpC,QAAM,YAAY,IAAI,WAAW,GAAG;AASnC,KAAC,SAAS,aAAc;AACvB,UAAI,IAAI;AACR,eAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,kBAAU,CAAC,IAAI;AACf,kBAAU,CAAC,IAAI;AAEf,cAAM;AAIN,YAAI,IAAI,KAAO;AACb,eAAK;AAAA,QACP;AAAA,MACF;AAMA,eAAS,IAAI,KAAK,IAAI,KAAK,KAAK;AAC9B,kBAAU,CAAC,IAAI,UAAU,IAAI,GAAG;AAAA,MAClC;AAAA,IACF,GAAE;AAQF,YAAQ,MAAM,SAAS,IAAK,GAAG;AAC7B,UAAI,IAAI,EAAG,OAAM,IAAI,MAAM,SAAS,IAAI,GAAG;AAC3C,aAAO,UAAU,CAAC;AAAA,IACpB;AAQA,YAAQ,MAAM,SAAS,IAAK,GAAG;AAC7B,aAAO,UAAU,CAAC;AAAA,IACpB;AASA,YAAQ,MAAM,SAAS,IAAK,GAAG,GAAG;AAChC,UAAI,MAAM,KAAK,MAAM,EAAG,QAAO;AAI/B,aAAO,UAAU,UAAU,CAAC,IAAI,UAAU,CAAC,CAAC;AAAA,IAC9C;AAAA;AAAA;;;ACpEA;AAAA;AAAA,QAAM,KAAK;AASX,YAAQ,MAAM,SAAS,IAAK,IAAI,IAAI;AAClC,YAAM,QAAQ,IAAI,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;AAEtD,eAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,KAAK;AAClC,iBAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,KAAK;AAClC,gBAAM,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;AAAA,QACrC;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AASA,YAAQ,MAAM,SAAS,IAAK,UAAU,SAAS;AAC7C,UAAI,SAAS,IAAI,WAAW,QAAQ;AAEpC,aAAQ,OAAO,SAAS,QAAQ,UAAW,GAAG;AAC5C,cAAM,QAAQ,OAAO,CAAC;AAEtB,iBAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,iBAAO,CAAC,KAAK,GAAG,IAAI,QAAQ,CAAC,GAAG,KAAK;AAAA,QACvC;AAGA,YAAI,SAAS;AACb,eAAO,SAAS,OAAO,UAAU,OAAO,MAAM,MAAM,EAAG;AACvD,iBAAS,OAAO,MAAM,MAAM;AAAA,MAC9B;AAEA,aAAO;AAAA,IACT;AASA,YAAQ,uBAAuB,SAAS,qBAAsB,QAAQ;AACpE,UAAI,OAAO,IAAI,WAAW,CAAC,CAAC,CAAC;AAC7B,eAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,eAAO,QAAQ,IAAI,MAAM,IAAI,WAAW,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAAA,MACzD;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;;;AC7DA;AAAA;AAAA,QAAM,aAAa;AAEnB,aAAS,mBAAoB,QAAQ;AACnC,WAAK,UAAU;AACf,WAAK,SAAS;AAEd,UAAI,KAAK,OAAQ,MAAK,WAAW,KAAK,MAAM;AAAA,IAC9C;AAQA,uBAAmB,UAAU,aAAa,SAAS,WAAY,QAAQ;AAErE,WAAK,SAAS;AACd,WAAK,UAAU,WAAW,qBAAqB,KAAK,MAAM;AAAA,IAC5D;AAQA,uBAAmB,UAAU,SAAS,SAAS,OAAQ,MAAM;AAC3D,UAAI,CAAC,KAAK,SAAS;AACjB,cAAM,IAAI,MAAM,yBAAyB;AAAA,MAC3C;AAIA,YAAM,aAAa,IAAI,WAAW,KAAK,SAAS,KAAK,MAAM;AAC3D,iBAAW,IAAI,IAAI;AAInB,YAAM,YAAY,WAAW,IAAI,YAAY,KAAK,OAAO;AAKzD,YAAM,QAAQ,KAAK,SAAS,UAAU;AACtC,UAAI,QAAQ,GAAG;AACb,cAAM,OAAO,IAAI,WAAW,KAAK,MAAM;AACvC,aAAK,IAAI,WAAW,KAAK;AAEzB,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAEA,WAAO,UAAU;AAAA;AAAA;;;ACvDjB;AAAA;AAMA,YAAQ,UAAU,SAAS,QAAS,SAAS;AAC3C,aAAO,CAAC,MAAM,OAAO,KAAK,WAAW,KAAK,WAAW;AAAA,IACvD;AAAA;AAAA;;;ACRA;AAAA;AAAA,QAAM,UAAU;AAChB,QAAM,eAAe;AACrB,QAAI,QAAQ;AAIZ,YAAQ,MAAM,QAAQ,MAAM,KAAK;AAEjC,QAAM,OAAO,+BAA+B,QAAQ;AAEpD,YAAQ,QAAQ,IAAI,OAAO,OAAO,GAAG;AACrC,YAAQ,aAAa,IAAI,OAAO,yBAAyB,GAAG;AAC5D,YAAQ,OAAO,IAAI,OAAO,MAAM,GAAG;AACnC,YAAQ,UAAU,IAAI,OAAO,SAAS,GAAG;AACzC,YAAQ,eAAe,IAAI,OAAO,cAAc,GAAG;AAEnD,QAAM,aAAa,IAAI,OAAO,MAAM,QAAQ,GAAG;AAC/C,QAAM,eAAe,IAAI,OAAO,MAAM,UAAU,GAAG;AACnD,QAAM,oBAAoB,IAAI,OAAO,wBAAwB;AAE7D,YAAQ,YAAY,SAAS,UAAW,KAAK;AAC3C,aAAO,WAAW,KAAK,GAAG;AAAA,IAC5B;AAEA,YAAQ,cAAc,SAAS,YAAa,KAAK;AAC/C,aAAO,aAAa,KAAK,GAAG;AAAA,IAC9B;AAEA,YAAQ,mBAAmB,SAAS,iBAAkB,KAAK;AACzD,aAAO,kBAAkB,KAAK,GAAG;AAAA,IACnC;AAAA;AAAA;;;AC9BA;AAAA;AAAA,QAAM,eAAe;AACrB,QAAM,QAAQ;AASd,YAAQ,UAAU;AAAA,MAChB,IAAI;AAAA,MACJ,KAAK,KAAK;AAAA,MACV,QAAQ,CAAC,IAAI,IAAI,EAAE;AAAA,IACrB;AAWA,YAAQ,eAAe;AAAA,MACrB,IAAI;AAAA,MACJ,KAAK,KAAK;AAAA,MACV,QAAQ,CAAC,GAAG,IAAI,EAAE;AAAA,IACpB;AAOA,YAAQ,OAAO;AAAA,MACb,IAAI;AAAA,MACJ,KAAK,KAAK;AAAA,MACV,QAAQ,CAAC,GAAG,IAAI,EAAE;AAAA,IACpB;AAWA,YAAQ,QAAQ;AAAA,MACd,IAAI;AAAA,MACJ,KAAK,KAAK;AAAA,MACV,QAAQ,CAAC,GAAG,IAAI,EAAE;AAAA,IACpB;AAQA,YAAQ,QAAQ;AAAA,MACd,KAAK;AAAA,IACP;AAUA,YAAQ,wBAAwB,SAAS,sBAAuB,MAAM,SAAS;AAC7E,UAAI,CAAC,KAAK,OAAQ,OAAM,IAAI,MAAM,mBAAmB,IAAI;AAEzD,UAAI,CAAC,aAAa,QAAQ,OAAO,GAAG;AAClC,cAAM,IAAI,MAAM,sBAAsB,OAAO;AAAA,MAC/C;AAEA,UAAI,WAAW,KAAK,UAAU,GAAI,QAAO,KAAK,OAAO,CAAC;AAAA,eAC7C,UAAU,GAAI,QAAO,KAAK,OAAO,CAAC;AAC3C,aAAO,KAAK,OAAO,CAAC;AAAA,IACtB;AAQA,YAAQ,qBAAqB,SAAS,mBAAoB,SAAS;AACjE,UAAI,MAAM,YAAY,OAAO,EAAG,QAAO,QAAQ;AAAA,eACtC,MAAM,iBAAiB,OAAO,EAAG,QAAO,QAAQ;AAAA,eAChD,MAAM,UAAU,OAAO,EAAG,QAAO,QAAQ;AAAA,UAC7C,QAAO,QAAQ;AAAA,IACtB;AAQA,YAAQ,WAAW,SAAS,SAAU,MAAM;AAC1C,UAAI,QAAQ,KAAK,GAAI,QAAO,KAAK;AACjC,YAAM,IAAI,MAAM,cAAc;AAAA,IAChC;AAQA,YAAQ,UAAU,SAAS,QAAS,MAAM;AACxC,aAAO,QAAQ,KAAK,OAAO,KAAK;AAAA,IAClC;AAQA,aAAS,WAAY,QAAQ;AAC3B,UAAI,OAAO,WAAW,UAAU;AAC9B,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AAEA,YAAM,QAAQ,OAAO,YAAY;AAEjC,cAAQ,OAAO;AAAA,QACb,KAAK;AACH,iBAAO,QAAQ;AAAA,QACjB,KAAK;AACH,iBAAO,QAAQ;AAAA,QACjB,KAAK;AACH,iBAAO,QAAQ;AAAA,QACjB,KAAK;AACH,iBAAO,QAAQ;AAAA,QACjB;AACE,gBAAM,IAAI,MAAM,mBAAmB,MAAM;AAAA,MAC7C;AAAA,IACF;AAUA,YAAQ,OAAO,SAAS,KAAM,OAAO,cAAc;AACjD,UAAI,QAAQ,QAAQ,KAAK,GAAG;AAC1B,eAAO;AAAA,MACT;AAEA,UAAI;AACF,eAAO,WAAW,KAAK;AAAA,MACzB,SAAS,GAAG;AACV,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;;;ACtKA;AAAA;AAAA,QAAM,QAAQ;AACd,QAAM,SAAS;AACf,QAAM,UAAU;AAChB,QAAM,OAAO;AACb,QAAM,eAAe;AAGrB,QAAM,MAAO,KAAK,KAAO,KAAK,KAAO,KAAK,KAAO,KAAK,IAAM,KAAK,IAAM,KAAK,IAAM,KAAK,IAAM,KAAK;AAClG,QAAM,UAAU,MAAM,YAAY,GAAG;AAErC,aAAS,4BAA6B,MAAM,QAAQ,sBAAsB;AACxE,eAAS,iBAAiB,GAAG,kBAAkB,IAAI,kBAAkB;AACnE,YAAI,UAAU,QAAQ,YAAY,gBAAgB,sBAAsB,IAAI,GAAG;AAC7E,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAEA,aAAS,qBAAsB,MAAM,SAAS;AAE5C,aAAO,KAAK,sBAAsB,MAAM,OAAO,IAAI;AAAA,IACrD;AAEA,aAAS,0BAA2B,UAAU,SAAS;AACrD,UAAI,YAAY;AAEhB,eAAS,QAAQ,SAAU,MAAM;AAC/B,cAAM,eAAe,qBAAqB,KAAK,MAAM,OAAO;AAC5D,qBAAa,eAAe,KAAK,cAAc;AAAA,MACjD,CAAC;AAED,aAAO;AAAA,IACT;AAEA,aAAS,2BAA4B,UAAU,sBAAsB;AACnE,eAAS,iBAAiB,GAAG,kBAAkB,IAAI,kBAAkB;AACnE,cAAM,SAAS,0BAA0B,UAAU,cAAc;AACjE,YAAI,UAAU,QAAQ,YAAY,gBAAgB,sBAAsB,KAAK,KAAK,GAAG;AACnF,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAUA,YAAQ,OAAO,SAAS,KAAM,OAAO,cAAc;AACjD,UAAI,aAAa,QAAQ,KAAK,GAAG;AAC/B,eAAO,SAAS,OAAO,EAAE;AAAA,MAC3B;AAEA,aAAO;AAAA,IACT;AAWA,YAAQ,cAAc,SAAS,YAAa,SAAS,sBAAsB,MAAM;AAC/E,UAAI,CAAC,aAAa,QAAQ,OAAO,GAAG;AAClC,cAAM,IAAI,MAAM,yBAAyB;AAAA,MAC3C;AAGA,UAAI,OAAO,SAAS,YAAa,QAAO,KAAK;AAG7C,YAAM,iBAAiB,MAAM,wBAAwB,OAAO;AAG5D,YAAM,mBAAmB,OAAO,uBAAuB,SAAS,oBAAoB;AAGpF,YAAM,0BAA0B,iBAAiB,oBAAoB;AAErE,UAAI,SAAS,KAAK,MAAO,QAAO;AAEhC,YAAM,aAAa,yBAAyB,qBAAqB,MAAM,OAAO;AAG9E,cAAQ,MAAM;AAAA,QACZ,KAAK,KAAK;AACR,iBAAO,KAAK,MAAO,aAAa,KAAM,CAAC;AAAA,QAEzC,KAAK,KAAK;AACR,iBAAO,KAAK,MAAO,aAAa,KAAM,CAAC;AAAA,QAEzC,KAAK,KAAK;AACR,iBAAO,KAAK,MAAM,aAAa,EAAE;AAAA,QAEnC,KAAK,KAAK;AAAA,QACV;AACE,iBAAO,KAAK,MAAM,aAAa,CAAC;AAAA,MACpC;AAAA,IACF;AAUA,YAAQ,wBAAwB,SAAS,sBAAuB,MAAM,sBAAsB;AAC1F,UAAI;AAEJ,YAAM,MAAM,QAAQ,KAAK,sBAAsB,QAAQ,CAAC;AAExD,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,YAAI,KAAK,SAAS,GAAG;AACnB,iBAAO,2BAA2B,MAAM,GAAG;AAAA,QAC7C;AAEA,YAAI,KAAK,WAAW,GAAG;AACrB,iBAAO;AAAA,QACT;AAEA,cAAM,KAAK,CAAC;AAAA,MACd,OAAO;AACL,cAAM;AAAA,MACR;AAEA,aAAO,4BAA4B,IAAI,MAAM,IAAI,UAAU,GAAG,GAAG;AAAA,IACnE;AAYA,YAAQ,iBAAiB,SAAS,eAAgB,SAAS;AACzD,UAAI,CAAC,aAAa,QAAQ,OAAO,KAAK,UAAU,GAAG;AACjD,cAAM,IAAI,MAAM,yBAAyB;AAAA,MAC3C;AAEA,UAAI,IAAI,WAAW;AAEnB,aAAO,MAAM,YAAY,CAAC,IAAI,WAAW,GAAG;AAC1C,aAAM,OAAQ,MAAM,YAAY,CAAC,IAAI;AAAA,MACvC;AAEA,aAAQ,WAAW,KAAM;AAAA,IAC3B;AAAA;AAAA;;;AClKA;AAAA;AAAA,QAAM,QAAQ;AAEd,QAAM,MAAO,KAAK,KAAO,KAAK,IAAM,KAAK,IAAM,KAAK,IAAM,KAAK,IAAM,KAAK,IAAM,KAAK;AACrF,QAAM,WAAY,KAAK,KAAO,KAAK,KAAO,KAAK,KAAO,KAAK,IAAM,KAAK;AACtE,QAAM,UAAU,MAAM,YAAY,GAAG;AAYrC,YAAQ,iBAAiB,SAAS,eAAgB,sBAAsB,MAAM;AAC5E,YAAM,OAAS,qBAAqB,OAAO,IAAK;AAChD,UAAI,IAAI,QAAQ;AAEhB,aAAO,MAAM,YAAY,CAAC,IAAI,WAAW,GAAG;AAC1C,aAAM,OAAQ,MAAM,YAAY,CAAC,IAAI;AAAA,MACvC;AAKA,cAAS,QAAQ,KAAM,KAAK;AAAA,IAC9B;AAAA;AAAA;;;AC5BA;AAAA;AAAA,QAAM,OAAO;AAEb,aAAS,YAAa,MAAM;AAC1B,WAAK,OAAO,KAAK;AACjB,WAAK,OAAO,KAAK,SAAS;AAAA,IAC5B;AAEA,gBAAY,gBAAgB,SAAS,cAAe,QAAQ;AAC1D,aAAO,KAAK,KAAK,MAAM,SAAS,CAAC,KAAM,SAAS,IAAO,SAAS,IAAK,IAAI,IAAK;AAAA,IAChF;AAEA,gBAAY,UAAU,YAAY,SAAS,YAAa;AACtD,aAAO,KAAK,KAAK;AAAA,IACnB;AAEA,gBAAY,UAAU,gBAAgB,SAAS,gBAAiB;AAC9D,aAAO,YAAY,cAAc,KAAK,KAAK,MAAM;AAAA,IACnD;AAEA,gBAAY,UAAU,QAAQ,SAAS,MAAO,WAAW;AACvD,UAAI,GAAG,OAAO;AAId,WAAK,IAAI,GAAG,IAAI,KAAK,KAAK,KAAK,QAAQ,KAAK,GAAG;AAC7C,gBAAQ,KAAK,KAAK,OAAO,GAAG,CAAC;AAC7B,gBAAQ,SAAS,OAAO,EAAE;AAE1B,kBAAU,IAAI,OAAO,EAAE;AAAA,MACzB;AAIA,YAAM,eAAe,KAAK,KAAK,SAAS;AACxC,UAAI,eAAe,GAAG;AACpB,gBAAQ,KAAK,KAAK,OAAO,CAAC;AAC1B,gBAAQ,SAAS,OAAO,EAAE;AAE1B,kBAAU,IAAI,OAAO,eAAe,IAAI,CAAC;AAAA,MAC3C;AAAA,IACF;AAEA,WAAO,UAAU;AAAA;AAAA;;;AC1CjB;AAAA;AAAA,QAAM,OAAO;AAWb,QAAM,kBAAkB;AAAA,MACtB;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAC7C;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAC5D;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAC5D;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,MAAK;AAAA,IAC1C;AAEA,aAAS,iBAAkB,MAAM;AAC/B,WAAK,OAAO,KAAK;AACjB,WAAK,OAAO;AAAA,IACd;AAEA,qBAAiB,gBAAgB,SAAS,cAAe,QAAQ;AAC/D,aAAO,KAAK,KAAK,MAAM,SAAS,CAAC,IAAI,KAAK,SAAS;AAAA,IACrD;AAEA,qBAAiB,UAAU,YAAY,SAAS,YAAa;AAC3D,aAAO,KAAK,KAAK;AAAA,IACnB;AAEA,qBAAiB,UAAU,gBAAgB,SAAS,gBAAiB;AACnE,aAAO,iBAAiB,cAAc,KAAK,KAAK,MAAM;AAAA,IACxD;AAEA,qBAAiB,UAAU,QAAQ,SAAS,MAAO,WAAW;AAC5D,UAAI;AAIJ,WAAK,IAAI,GAAG,IAAI,KAAK,KAAK,KAAK,QAAQ,KAAK,GAAG;AAE7C,YAAI,QAAQ,gBAAgB,QAAQ,KAAK,KAAK,CAAC,CAAC,IAAI;AAGpD,iBAAS,gBAAgB,QAAQ,KAAK,KAAK,IAAI,CAAC,CAAC;AAGjD,kBAAU,IAAI,OAAO,EAAE;AAAA,MACzB;AAIA,UAAI,KAAK,KAAK,SAAS,GAAG;AACxB,kBAAU,IAAI,gBAAgB,QAAQ,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC;AAAA,MACxD;AAAA,IACF;AAEA,WAAO,UAAU;AAAA;AAAA;;;AC1DjB;AAAA;AAAA,QAAM,OAAO;AAEb,aAAS,SAAU,MAAM;AACvB,WAAK,OAAO,KAAK;AACjB,UAAI,OAAQ,SAAU,UAAU;AAC9B,aAAK,OAAO,IAAI,YAAY,EAAE,OAAO,IAAI;AAAA,MAC3C,OAAO;AACL,aAAK,OAAO,IAAI,WAAW,IAAI;AAAA,MACjC;AAAA,IACF;AAEA,aAAS,gBAAgB,SAAS,cAAe,QAAQ;AACvD,aAAO,SAAS;AAAA,IAClB;AAEA,aAAS,UAAU,YAAY,SAAS,YAAa;AACnD,aAAO,KAAK,KAAK;AAAA,IACnB;AAEA,aAAS,UAAU,gBAAgB,SAAS,gBAAiB;AAC3D,aAAO,SAAS,cAAc,KAAK,KAAK,MAAM;AAAA,IAChD;AAEA,aAAS,UAAU,QAAQ,SAAU,WAAW;AAC9C,eAAS,IAAI,GAAG,IAAI,KAAK,KAAK,QAAQ,IAAI,GAAG,KAAK;AAChD,kBAAU,IAAI,KAAK,KAAK,CAAC,GAAG,CAAC;AAAA,MAC/B;AAAA,IACF;AAEA,WAAO,UAAU;AAAA;AAAA;;;AC7BjB;AAAA;AAAA,QAAM,OAAO;AACb,QAAM,QAAQ;AAEd,aAAS,UAAW,MAAM;AACxB,WAAK,OAAO,KAAK;AACjB,WAAK,OAAO;AAAA,IACd;AAEA,cAAU,gBAAgB,SAAS,cAAe,QAAQ;AACxD,aAAO,SAAS;AAAA,IAClB;AAEA,cAAU,UAAU,YAAY,SAAS,YAAa;AACpD,aAAO,KAAK,KAAK;AAAA,IACnB;AAEA,cAAU,UAAU,gBAAgB,SAAS,gBAAiB;AAC5D,aAAO,UAAU,cAAc,KAAK,KAAK,MAAM;AAAA,IACjD;AAEA,cAAU,UAAU,QAAQ,SAAU,WAAW;AAC/C,UAAI;AAKJ,WAAK,IAAI,GAAG,IAAI,KAAK,KAAK,QAAQ,KAAK;AACrC,YAAI,QAAQ,MAAM,OAAO,KAAK,KAAK,CAAC,CAAC;AAGrC,YAAI,SAAS,SAAU,SAAS,OAAQ;AAEtC,mBAAS;AAAA,QAGX,WAAW,SAAS,SAAU,SAAS,OAAQ;AAE7C,mBAAS;AAAA,QACX,OAAO;AACL,gBAAM,IAAI;AAAA,YACR,6BAA6B,KAAK,KAAK,CAAC,IAAI;AAAA,UACX;AAAA,QACrC;AAIA,iBAAW,UAAU,IAAK,OAAQ,OAAS,QAAQ;AAGnD,kBAAU,IAAI,OAAO,EAAE;AAAA,MACzB;AAAA,IACF;AAEA,WAAO,UAAU;AAAA;AAAA;;;ACrDjB;AAAA;AAAA;AAuBA,QAAI,WAAW;AAAA,MACb,8BAA8B,SAAS,OAAO,GAAG,GAAG;AAGlD,YAAI,eAAe,CAAC;AAIpB,YAAI,QAAQ,CAAC;AACb,cAAM,CAAC,IAAI;AAMX,YAAI,OAAO,SAAS,cAAc,KAAK;AACvC,aAAK,KAAK,GAAG,CAAC;AAEd,YAAI,SACA,GAAG,GACH,gBACA,gBACA,WACA,+BACA,gBACA;AACJ,eAAO,CAAC,KAAK,MAAM,GAAG;AAGpB,oBAAU,KAAK,IAAI;AACnB,cAAI,QAAQ;AACZ,2BAAiB,QAAQ;AAGzB,2BAAiB,MAAM,CAAC,KAAK,CAAC;AAK9B,eAAK,KAAK,gBAAgB;AACxB,gBAAI,eAAe,eAAe,CAAC,GAAG;AAEpC,0BAAY,eAAe,CAAC;AAK5B,8CAAgC,iBAAiB;AAMjD,+BAAiB,MAAM,CAAC;AACxB,4BAAe,OAAO,MAAM,CAAC,MAAM;AACnC,kBAAI,eAAe,iBAAiB,+BAA+B;AACjE,sBAAM,CAAC,IAAI;AACX,qBAAK,KAAK,GAAG,6BAA6B;AAC1C,6BAAa,CAAC,IAAI;AAAA,cACpB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,YAAI,OAAO,MAAM,eAAe,OAAO,MAAM,CAAC,MAAM,aAAa;AAC/D,cAAI,MAAM,CAAC,+BAA+B,GAAG,QAAQ,GAAG,GAAG,EAAE,KAAK,EAAE;AACpE,gBAAM,IAAI,MAAM,GAAG;AAAA,QACrB;AAEA,eAAO;AAAA,MACT;AAAA,MAEA,6CAA6C,SAAS,cAAc,GAAG;AACrE,YAAI,QAAQ,CAAC;AACb,YAAI,IAAI;AACR,YAAI;AACJ,eAAO,GAAG;AACR,gBAAM,KAAK,CAAC;AACZ,wBAAc,aAAa,CAAC;AAC5B,cAAI,aAAa,CAAC;AAAA,QACpB;AACA,cAAM,QAAQ;AACd,eAAO;AAAA,MACT;AAAA,MAEA,WAAW,SAAS,OAAO,GAAG,GAAG;AAC/B,YAAI,eAAe,SAAS,6BAA6B,OAAO,GAAG,CAAC;AACpE,eAAO,SAAS;AAAA,UACd;AAAA,UAAc;AAAA,QAAC;AAAA,MACnB;AAAA;AAAA;AAAA;AAAA,MAKA,eAAe;AAAA,QACb,MAAM,SAAU,MAAM;AACpB,cAAI,IAAI,SAAS,eACb,IAAI,CAAC,GACL;AACJ,iBAAO,QAAQ,CAAC;AAChB,eAAK,OAAO,GAAG;AACb,gBAAI,EAAE,eAAe,GAAG,GAAG;AACzB,gBAAE,GAAG,IAAI,EAAE,GAAG;AAAA,YAChB;AAAA,UACF;AACA,YAAE,QAAQ,CAAC;AACX,YAAE,SAAS,KAAK,UAAU,EAAE;AAC5B,iBAAO;AAAA,QACT;AAAA,QAEA,gBAAgB,SAAU,GAAG,GAAG;AAC9B,iBAAO,EAAE,OAAO,EAAE;AAAA,QACpB;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,MAAM,SAAU,OAAO,MAAM;AAC3B,cAAI,OAAO,EAAC,OAAc,KAAU;AACpC,eAAK,MAAM,KAAK,IAAI;AACpB,eAAK,MAAM,KAAK,KAAK,MAAM;AAAA,QAC7B;AAAA;AAAA;AAAA;AAAA,QAKA,KAAK,WAAY;AACf,iBAAO,KAAK,MAAM,MAAM;AAAA,QAC1B;AAAA,QAEA,OAAO,WAAY;AACjB,iBAAO,KAAK,MAAM,WAAW;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AAIA,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,UAAU;AAAA,IACnB;AAAA;AAAA;;;ACpKA;AAAA;AAAA,QAAM,OAAO;AACb,QAAM,cAAc;AACpB,QAAM,mBAAmB;AACzB,QAAM,WAAW;AACjB,QAAM,YAAY;AAClB,QAAM,QAAQ;AACd,QAAM,QAAQ;AACd,QAAM,WAAW;AAQjB,aAAS,oBAAqB,KAAK;AACjC,aAAO,SAAS,mBAAmB,GAAG,CAAC,EAAE;AAAA,IAC3C;AAUA,aAAS,YAAa,OAAO,MAAM,KAAK;AACtC,YAAM,WAAW,CAAC;AAClB,UAAI;AAEJ,cAAQ,SAAS,MAAM,KAAK,GAAG,OAAO,MAAM;AAC1C,iBAAS,KAAK;AAAA,UACZ,MAAM,OAAO,CAAC;AAAA,UACd,OAAO,OAAO;AAAA,UACd;AAAA,UACA,QAAQ,OAAO,CAAC,EAAE;AAAA,QACpB,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,IACT;AASA,aAAS,sBAAuB,SAAS;AACvC,YAAM,UAAU,YAAY,MAAM,SAAS,KAAK,SAAS,OAAO;AAChE,YAAM,eAAe,YAAY,MAAM,cAAc,KAAK,cAAc,OAAO;AAC/E,UAAI;AACJ,UAAI;AAEJ,UAAI,MAAM,mBAAmB,GAAG;AAC9B,mBAAW,YAAY,MAAM,MAAM,KAAK,MAAM,OAAO;AACrD,oBAAY,YAAY,MAAM,OAAO,KAAK,OAAO,OAAO;AAAA,MAC1D,OAAO;AACL,mBAAW,YAAY,MAAM,YAAY,KAAK,MAAM,OAAO;AAC3D,oBAAY,CAAC;AAAA,MACf;AAEA,YAAM,OAAO,QAAQ,OAAO,cAAc,UAAU,SAAS;AAE7D,aAAO,KACJ,KAAK,SAAU,IAAI,IAAI;AACtB,eAAO,GAAG,QAAQ,GAAG;AAAA,MACvB,CAAC,EACA,IAAI,SAAU,KAAK;AAClB,eAAO;AAAA,UACL,MAAM,IAAI;AAAA,UACV,MAAM,IAAI;AAAA,UACV,QAAQ,IAAI;AAAA,QACd;AAAA,MACF,CAAC;AAAA,IACL;AAUA,aAAS,qBAAsB,QAAQ,MAAM;AAC3C,cAAQ,MAAM;AAAA,QACZ,KAAK,KAAK;AACR,iBAAO,YAAY,cAAc,MAAM;AAAA,QACzC,KAAK,KAAK;AACR,iBAAO,iBAAiB,cAAc,MAAM;AAAA,QAC9C,KAAK,KAAK;AACR,iBAAO,UAAU,cAAc,MAAM;AAAA,QACvC,KAAK,KAAK;AACR,iBAAO,SAAS,cAAc,MAAM;AAAA,MACxC;AAAA,IACF;AAQA,aAAS,cAAe,MAAM;AAC5B,aAAO,KAAK,OAAO,SAAU,KAAK,MAAM;AACtC,cAAM,UAAU,IAAI,SAAS,KAAK,IAAI,IAAI,IAAI,SAAS,CAAC,IAAI;AAC5D,YAAI,WAAW,QAAQ,SAAS,KAAK,MAAM;AACzC,cAAI,IAAI,SAAS,CAAC,EAAE,QAAQ,KAAK;AACjC,iBAAO;AAAA,QACT;AAEA,YAAI,KAAK,IAAI;AACb,eAAO;AAAA,MACT,GAAG,CAAC,CAAC;AAAA,IACP;AAkBA,aAAS,WAAY,MAAM;AACzB,YAAM,QAAQ,CAAC;AACf,eAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,cAAM,MAAM,KAAK,CAAC;AAElB,gBAAQ,IAAI,MAAM;AAAA,UAChB,KAAK,KAAK;AACR,kBAAM,KAAK;AAAA,cAAC;AAAA,cACV,EAAE,MAAM,IAAI,MAAM,MAAM,KAAK,cAAc,QAAQ,IAAI,OAAO;AAAA,cAC9D,EAAE,MAAM,IAAI,MAAM,MAAM,KAAK,MAAM,QAAQ,IAAI,OAAO;AAAA,YACxD,CAAC;AACD;AAAA,UACF,KAAK,KAAK;AACR,kBAAM,KAAK;AAAA,cAAC;AAAA,cACV,EAAE,MAAM,IAAI,MAAM,MAAM,KAAK,MAAM,QAAQ,IAAI,OAAO;AAAA,YACxD,CAAC;AACD;AAAA,UACF,KAAK,KAAK;AACR,kBAAM,KAAK;AAAA,cAAC;AAAA,cACV,EAAE,MAAM,IAAI,MAAM,MAAM,KAAK,MAAM,QAAQ,oBAAoB,IAAI,IAAI,EAAE;AAAA,YAC3E,CAAC;AACD;AAAA,UACF,KAAK,KAAK;AACR,kBAAM,KAAK;AAAA,cACT,EAAE,MAAM,IAAI,MAAM,MAAM,KAAK,MAAM,QAAQ,oBAAoB,IAAI,IAAI,EAAE;AAAA,YAC3E,CAAC;AAAA,QACL;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAcA,aAAS,WAAY,OAAO,SAAS;AACnC,YAAM,QAAQ,CAAC;AACf,YAAM,QAAQ,EAAE,OAAO,CAAC,EAAE;AAC1B,UAAI,cAAc,CAAC,OAAO;AAE1B,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,cAAM,YAAY,MAAM,CAAC;AACzB,cAAM,iBAAiB,CAAC;AAExB,iBAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,gBAAM,OAAO,UAAU,CAAC;AACxB,gBAAM,MAAM,KAAK,IAAI;AAErB,yBAAe,KAAK,GAAG;AACvB,gBAAM,GAAG,IAAI,EAAE,MAAY,WAAW,EAAE;AACxC,gBAAM,GAAG,IAAI,CAAC;AAEd,mBAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,kBAAM,aAAa,YAAY,CAAC;AAEhC,gBAAI,MAAM,UAAU,KAAK,MAAM,UAAU,EAAE,KAAK,SAAS,KAAK,MAAM;AAClE,oBAAM,UAAU,EAAE,GAAG,IACnB,qBAAqB,MAAM,UAAU,EAAE,YAAY,KAAK,QAAQ,KAAK,IAAI,IACzE,qBAAqB,MAAM,UAAU,EAAE,WAAW,KAAK,IAAI;AAE7D,oBAAM,UAAU,EAAE,aAAa,KAAK;AAAA,YACtC,OAAO;AACL,kBAAI,MAAM,UAAU,EAAG,OAAM,UAAU,EAAE,YAAY,KAAK;AAE1D,oBAAM,UAAU,EAAE,GAAG,IAAI,qBAAqB,KAAK,QAAQ,KAAK,IAAI,IAClE,IAAI,KAAK,sBAAsB,KAAK,MAAM,OAAO;AAAA,YACrD;AAAA,UACF;AAAA,QACF;AAEA,sBAAc;AAAA,MAChB;AAEA,eAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,cAAM,YAAY,CAAC,CAAC,EAAE,MAAM;AAAA,MAC9B;AAEA,aAAO,EAAE,KAAK,OAAO,MAAa;AAAA,IACpC;AAUA,aAAS,mBAAoB,MAAM,WAAW;AAC5C,UAAI;AACJ,YAAM,WAAW,KAAK,mBAAmB,IAAI;AAE7C,aAAO,KAAK,KAAK,WAAW,QAAQ;AAGpC,UAAI,SAAS,KAAK,QAAQ,KAAK,MAAM,SAAS,KAAK;AACjD,cAAM,IAAI,MAAM,MAAM,OAAO,mCACO,KAAK,SAAS,IAAI,IACpD,4BAA4B,KAAK,SAAS,QAAQ,CAAC;AAAA,MACvD;AAGA,UAAI,SAAS,KAAK,SAAS,CAAC,MAAM,mBAAmB,GAAG;AACtD,eAAO,KAAK;AAAA,MACd;AAEA,cAAQ,MAAM;AAAA,QACZ,KAAK,KAAK;AACR,iBAAO,IAAI,YAAY,IAAI;AAAA,QAE7B,KAAK,KAAK;AACR,iBAAO,IAAI,iBAAiB,IAAI;AAAA,QAElC,KAAK,KAAK;AACR,iBAAO,IAAI,UAAU,IAAI;AAAA,QAE3B,KAAK,KAAK;AACR,iBAAO,IAAI,SAAS,IAAI;AAAA,MAC5B;AAAA,IACF;AAiBA,YAAQ,YAAY,SAAS,UAAW,OAAO;AAC7C,aAAO,MAAM,OAAO,SAAU,KAAK,KAAK;AACtC,YAAI,OAAO,QAAQ,UAAU;AAC3B,cAAI,KAAK,mBAAmB,KAAK,IAAI,CAAC;AAAA,QACxC,WAAW,IAAI,MAAM;AACnB,cAAI,KAAK,mBAAmB,IAAI,MAAM,IAAI,IAAI,CAAC;AAAA,QACjD;AAEA,eAAO;AAAA,MACT,GAAG,CAAC,CAAC;AAAA,IACP;AAUA,YAAQ,aAAa,SAAS,WAAY,MAAM,SAAS;AACvD,YAAM,OAAO,sBAAsB,MAAM,MAAM,mBAAmB,CAAC;AAEnE,YAAM,QAAQ,WAAW,IAAI;AAC7B,YAAM,QAAQ,WAAW,OAAO,OAAO;AACvC,YAAM,OAAO,SAAS,UAAU,MAAM,KAAK,SAAS,KAAK;AAEzD,YAAM,gBAAgB,CAAC;AACvB,eAAS,IAAI,GAAG,IAAI,KAAK,SAAS,GAAG,KAAK;AACxC,sBAAc,KAAK,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,IAAI;AAAA,MAC9C;AAEA,aAAO,QAAQ,UAAU,cAAc,aAAa,CAAC;AAAA,IACvD;AAYA,YAAQ,WAAW,SAAS,SAAU,MAAM;AAC1C,aAAO,QAAQ;AAAA,QACb,sBAAsB,MAAM,MAAM,mBAAmB,CAAC;AAAA,MACxD;AAAA,IACF;AAAA;AAAA;;;ACzUA;AAAA;AAAA,QAAM,QAAQ;AACd,QAAM,UAAU;AAChB,QAAM,YAAY;AAClB,QAAM,YAAY;AAClB,QAAM,mBAAmB;AACzB,QAAM,gBAAgB;AACtB,QAAM,cAAc;AACpB,QAAM,SAAS;AACf,QAAM,qBAAqB;AAC3B,QAAM,UAAU;AAChB,QAAM,aAAa;AACnB,QAAM,OAAO;AACb,QAAM,WAAW;AAkCjB,aAAS,mBAAoB,QAAQ,SAAS;AAC5C,YAAM,OAAO,OAAO;AACpB,YAAM,MAAM,cAAc,aAAa,OAAO;AAE9C,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,cAAM,MAAM,IAAI,CAAC,EAAE,CAAC;AACpB,cAAM,MAAM,IAAI,CAAC,EAAE,CAAC;AAEpB,iBAAS,IAAI,IAAI,KAAK,GAAG,KAAK;AAC5B,cAAI,MAAM,KAAK,MAAM,QAAQ,MAAM,EAAG;AAEtC,mBAAS,IAAI,IAAI,KAAK,GAAG,KAAK;AAC5B,gBAAI,MAAM,KAAK,MAAM,QAAQ,MAAM,EAAG;AAEtC,gBAAK,KAAK,KAAK,KAAK,MAAM,MAAM,KAAK,MAAM,MACxC,KAAK,KAAK,KAAK,MAAM,MAAM,KAAK,MAAM,MACtC,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAI;AACxC,qBAAO,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI;AAAA,YACzC,OAAO;AACL,qBAAO,IAAI,MAAM,GAAG,MAAM,GAAG,OAAO,IAAI;AAAA,YAC1C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AASA,aAAS,mBAAoB,QAAQ;AACnC,YAAM,OAAO,OAAO;AAEpB,eAAS,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK;AACjC,cAAM,QAAQ,IAAI,MAAM;AACxB,eAAO,IAAI,GAAG,GAAG,OAAO,IAAI;AAC5B,eAAO,IAAI,GAAG,GAAG,OAAO,IAAI;AAAA,MAC9B;AAAA,IACF;AAUA,aAAS,sBAAuB,QAAQ,SAAS;AAC/C,YAAM,MAAM,iBAAiB,aAAa,OAAO;AAEjD,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,cAAM,MAAM,IAAI,CAAC,EAAE,CAAC;AACpB,cAAM,MAAM,IAAI,CAAC,EAAE,CAAC;AAEpB,iBAAS,IAAI,IAAI,KAAK,GAAG,KAAK;AAC5B,mBAAS,IAAI,IAAI,KAAK,GAAG,KAAK;AAC5B,gBAAI,MAAM,MAAM,MAAM,KAAK,MAAM,MAAM,MAAM,KAC1C,MAAM,KAAK,MAAM,GAAI;AACtB,qBAAO,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI;AAAA,YACzC,OAAO;AACL,qBAAO,IAAI,MAAM,GAAG,MAAM,GAAG,OAAO,IAAI;AAAA,YAC1C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAQA,aAAS,iBAAkB,QAAQ,SAAS;AAC1C,YAAM,OAAO,OAAO;AACpB,YAAM,OAAO,QAAQ,eAAe,OAAO;AAC3C,UAAI,KAAK,KAAK;AAEd,eAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,cAAM,KAAK,MAAM,IAAI,CAAC;AACtB,cAAM,IAAI,IAAI,OAAO,IAAI;AACzB,eAAQ,QAAQ,IAAK,OAAO;AAE5B,eAAO,IAAI,KAAK,KAAK,KAAK,IAAI;AAC9B,eAAO,IAAI,KAAK,KAAK,KAAK,IAAI;AAAA,MAChC;AAAA,IACF;AASA,aAAS,gBAAiB,QAAQ,sBAAsB,aAAa;AACnE,YAAM,OAAO,OAAO;AACpB,YAAM,OAAO,WAAW,eAAe,sBAAsB,WAAW;AACxE,UAAI,GAAG;AAEP,WAAK,IAAI,GAAG,IAAI,IAAI,KAAK;AACvB,eAAQ,QAAQ,IAAK,OAAO;AAG5B,YAAI,IAAI,GAAG;AACT,iBAAO,IAAI,GAAG,GAAG,KAAK,IAAI;AAAA,QAC5B,WAAW,IAAI,GAAG;AAChB,iBAAO,IAAI,IAAI,GAAG,GAAG,KAAK,IAAI;AAAA,QAChC,OAAO;AACL,iBAAO,IAAI,OAAO,KAAK,GAAG,GAAG,KAAK,IAAI;AAAA,QACxC;AAGA,YAAI,IAAI,GAAG;AACT,iBAAO,IAAI,GAAG,OAAO,IAAI,GAAG,KAAK,IAAI;AAAA,QACvC,WAAW,IAAI,GAAG;AAChB,iBAAO,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI;AAAA,QACzC,OAAO;AACL,iBAAO,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI;AAAA,QACrC;AAAA,MACF;AAGA,aAAO,IAAI,OAAO,GAAG,GAAG,GAAG,IAAI;AAAA,IACjC;AAQA,aAAS,UAAW,QAAQ,MAAM;AAChC,YAAM,OAAO,OAAO;AACpB,UAAI,MAAM;AACV,UAAI,MAAM,OAAO;AACjB,UAAI,WAAW;AACf,UAAI,YAAY;AAEhB,eAAS,MAAM,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG;AAC1C,YAAI,QAAQ,EAAG;AAEf,eAAO,MAAM;AACX,mBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,gBAAI,CAAC,OAAO,WAAW,KAAK,MAAM,CAAC,GAAG;AACpC,kBAAI,OAAO;AAEX,kBAAI,YAAY,KAAK,QAAQ;AAC3B,wBAAU,KAAK,SAAS,MAAM,WAAY,OAAO;AAAA,cACnD;AAEA,qBAAO,IAAI,KAAK,MAAM,GAAG,IAAI;AAC7B;AAEA,kBAAI,aAAa,IAAI;AACnB;AACA,2BAAW;AAAA,cACb;AAAA,YACF;AAAA,UACF;AAEA,iBAAO;AAEP,cAAI,MAAM,KAAK,QAAQ,KAAK;AAC1B,mBAAO;AACP,kBAAM,CAAC;AACP;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAUA,aAAS,WAAY,SAAS,sBAAsB,UAAU;AAE5D,YAAM,SAAS,IAAI,UAAU;AAE7B,eAAS,QAAQ,SAAU,MAAM;AAE/B,eAAO,IAAI,KAAK,KAAK,KAAK,CAAC;AAS3B,eAAO,IAAI,KAAK,UAAU,GAAG,KAAK,sBAAsB,KAAK,MAAM,OAAO,CAAC;AAG3E,aAAK,MAAM,MAAM;AAAA,MACnB,CAAC;AAGD,YAAM,iBAAiB,MAAM,wBAAwB,OAAO;AAC5D,YAAM,mBAAmB,OAAO,uBAAuB,SAAS,oBAAoB;AACpF,YAAM,0BAA0B,iBAAiB,oBAAoB;AAOrE,UAAI,OAAO,gBAAgB,IAAI,KAAK,wBAAwB;AAC1D,eAAO,IAAI,GAAG,CAAC;AAAA,MACjB;AAOA,aAAO,OAAO,gBAAgB,IAAI,MAAM,GAAG;AACzC,eAAO,OAAO,CAAC;AAAA,MACjB;AAMA,YAAM,iBAAiB,yBAAyB,OAAO,gBAAgB,KAAK;AAC5E,eAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACtC,eAAO,IAAI,IAAI,IAAI,KAAO,KAAM,CAAC;AAAA,MACnC;AAEA,aAAO,gBAAgB,QAAQ,SAAS,oBAAoB;AAAA,IAC9D;AAWA,aAAS,gBAAiB,WAAW,SAAS,sBAAsB;AAElE,YAAM,iBAAiB,MAAM,wBAAwB,OAAO;AAG5D,YAAM,mBAAmB,OAAO,uBAAuB,SAAS,oBAAoB;AAGpF,YAAM,qBAAqB,iBAAiB;AAG5C,YAAM,gBAAgB,OAAO,eAAe,SAAS,oBAAoB;AAGzE,YAAM,iBAAiB,iBAAiB;AACxC,YAAM,iBAAiB,gBAAgB;AAEvC,YAAM,yBAAyB,KAAK,MAAM,iBAAiB,aAAa;AAExE,YAAM,wBAAwB,KAAK,MAAM,qBAAqB,aAAa;AAC3E,YAAM,wBAAwB,wBAAwB;AAGtD,YAAM,UAAU,yBAAyB;AAGzC,YAAM,KAAK,IAAI,mBAAmB,OAAO;AAEzC,UAAI,SAAS;AACb,YAAM,SAAS,IAAI,MAAM,aAAa;AACtC,YAAM,SAAS,IAAI,MAAM,aAAa;AACtC,UAAI,cAAc;AAClB,YAAM,SAAS,IAAI,WAAW,UAAU,MAAM;AAG9C,eAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACtC,cAAM,WAAW,IAAI,iBAAiB,wBAAwB;AAG9D,eAAO,CAAC,IAAI,OAAO,MAAM,QAAQ,SAAS,QAAQ;AAGlD,eAAO,CAAC,IAAI,GAAG,OAAO,OAAO,CAAC,CAAC;AAE/B,kBAAU;AACV,sBAAc,KAAK,IAAI,aAAa,QAAQ;AAAA,MAC9C;AAIA,YAAM,OAAO,IAAI,WAAW,cAAc;AAC1C,UAAI,QAAQ;AACZ,UAAI,GAAG;AAGP,WAAK,IAAI,GAAG,IAAI,aAAa,KAAK;AAChC,aAAK,IAAI,GAAG,IAAI,eAAe,KAAK;AAClC,cAAI,IAAI,OAAO,CAAC,EAAE,QAAQ;AACxB,iBAAK,OAAO,IAAI,OAAO,CAAC,EAAE,CAAC;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAGA,WAAK,IAAI,GAAG,IAAI,SAAS,KAAK;AAC5B,aAAK,IAAI,GAAG,IAAI,eAAe,KAAK;AAClC,eAAK,OAAO,IAAI,OAAO,CAAC,EAAE,CAAC;AAAA,QAC7B;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAWA,aAAS,aAAc,MAAM,SAAS,sBAAsB,aAAa;AACvE,UAAI;AAEJ,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,mBAAW,SAAS,UAAU,IAAI;AAAA,MACpC,WAAW,OAAO,SAAS,UAAU;AACnC,YAAI,mBAAmB;AAEvB,YAAI,CAAC,kBAAkB;AACrB,gBAAM,cAAc,SAAS,SAAS,IAAI;AAG1C,6BAAmB,QAAQ,sBAAsB,aAAa,oBAAoB;AAAA,QACpF;AAIA,mBAAW,SAAS,WAAW,MAAM,oBAAoB,EAAE;AAAA,MAC7D,OAAO;AACL,cAAM,IAAI,MAAM,cAAc;AAAA,MAChC;AAGA,YAAM,cAAc,QAAQ,sBAAsB,UAAU,oBAAoB;AAGhF,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,yDAAyD;AAAA,MAC3E;AAGA,UAAI,CAAC,SAAS;AACZ,kBAAU;AAAA,MAGZ,WAAW,UAAU,aAAa;AAChC,cAAM,IAAI;AAAA,UAAM,0HAE0C,cAAc;AAAA,QACxE;AAAA,MACF;AAEA,YAAM,WAAW,WAAW,SAAS,sBAAsB,QAAQ;AAGnE,YAAM,cAAc,MAAM,cAAc,OAAO;AAC/C,YAAM,UAAU,IAAI,UAAU,WAAW;AAGzC,yBAAmB,SAAS,OAAO;AACnC,yBAAmB,OAAO;AAC1B,4BAAsB,SAAS,OAAO;AAMtC,sBAAgB,SAAS,sBAAsB,CAAC;AAEhD,UAAI,WAAW,GAAG;AAChB,yBAAiB,SAAS,OAAO;AAAA,MACnC;AAGA,gBAAU,SAAS,QAAQ;AAE3B,UAAI,MAAM,WAAW,GAAG;AAEtB,sBAAc,YAAY;AAAA,UAAY;AAAA,UACpC,gBAAgB,KAAK,MAAM,SAAS,oBAAoB;AAAA,QAAC;AAAA,MAC7D;AAGA,kBAAY,UAAU,aAAa,OAAO;AAG1C,sBAAgB,SAAS,sBAAsB,WAAW;AAE1D,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAWA,YAAQ,SAAS,SAAS,OAAQ,MAAM,SAAS;AAC/C,UAAI,OAAO,SAAS,eAAe,SAAS,IAAI;AAC9C,cAAM,IAAI,MAAM,eAAe;AAAA,MACjC;AAEA,UAAI,uBAAuB,QAAQ;AACnC,UAAI;AACJ,UAAI;AAEJ,UAAI,OAAO,YAAY,aAAa;AAElC,+BAAuB,QAAQ,KAAK,QAAQ,sBAAsB,QAAQ,CAAC;AAC3E,kBAAU,QAAQ,KAAK,QAAQ,OAAO;AACtC,eAAO,YAAY,KAAK,QAAQ,WAAW;AAE3C,YAAI,QAAQ,YAAY;AACtB,gBAAM,kBAAkB,QAAQ,UAAU;AAAA,QAC5C;AAAA,MACF;AAEA,aAAO,aAAa,MAAM,SAAS,sBAAsB,IAAI;AAAA,IAC/D;AAAA;AAAA;;;AC9eA,IAAAC,iBAAA;AAAA;AAAA,aAAS,SAAU,KAAK;AACtB,UAAI,OAAO,QAAQ,UAAU;AAC3B,cAAM,IAAI,SAAS;AAAA,MACrB;AAEA,UAAI,OAAO,QAAQ,UAAU;AAC3B,cAAM,IAAI,MAAM,uCAAuC;AAAA,MACzD;AAEA,UAAI,UAAU,IAAI,MAAM,EAAE,QAAQ,KAAK,EAAE,EAAE,MAAM,EAAE;AACnD,UAAI,QAAQ,SAAS,KAAK,QAAQ,WAAW,KAAK,QAAQ,SAAS,GAAG;AACpE,cAAM,IAAI,MAAM,wBAAwB,GAAG;AAAA,MAC7C;AAGA,UAAI,QAAQ,WAAW,KAAK,QAAQ,WAAW,GAAG;AAChD,kBAAU,MAAM,UAAU,OAAO,MAAM,CAAC,GAAG,QAAQ,IAAI,SAAU,GAAG;AAClE,iBAAO,CAAC,GAAG,CAAC;AAAA,QACd,CAAC,CAAC;AAAA,MACJ;AAGA,UAAI,QAAQ,WAAW,EAAG,SAAQ,KAAK,KAAK,GAAG;AAE/C,YAAM,WAAW,SAAS,QAAQ,KAAK,EAAE,GAAG,EAAE;AAE9C,aAAO;AAAA,QACL,GAAI,YAAY,KAAM;AAAA,QACtB,GAAI,YAAY,KAAM;AAAA,QACtB,GAAI,YAAY,IAAK;AAAA,QACrB,GAAG,WAAW;AAAA,QACd,KAAK,MAAM,QAAQ,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE;AAAA,MACxC;AAAA,IACF;AAEA,YAAQ,aAAa,SAAS,WAAY,SAAS;AACjD,UAAI,CAAC,QAAS,WAAU,CAAC;AACzB,UAAI,CAAC,QAAQ,MAAO,SAAQ,QAAQ,CAAC;AAErC,YAAM,SAAS,OAAO,QAAQ,WAAW,eACvC,QAAQ,WAAW,QACnB,QAAQ,SAAS,IACf,IACA,QAAQ;AAEZ,YAAM,QAAQ,QAAQ,SAAS,QAAQ,SAAS,KAAK,QAAQ,QAAQ;AACrE,YAAM,QAAQ,QAAQ,SAAS;AAE/B,aAAO;AAAA,QACL;AAAA,QACA,OAAO,QAAQ,IAAI;AAAA,QACnB;AAAA,QACA,OAAO;AAAA,UACL,MAAM,SAAS,QAAQ,MAAM,QAAQ,WAAW;AAAA,UAChD,OAAO,SAAS,QAAQ,MAAM,SAAS,WAAW;AAAA,QACpD;AAAA,QACA,MAAM,QAAQ;AAAA,QACd,cAAc,QAAQ,gBAAgB,CAAC;AAAA,MACzC;AAAA,IACF;AAEA,YAAQ,WAAW,SAAS,SAAU,QAAQ,MAAM;AAClD,aAAO,KAAK,SAAS,KAAK,SAAS,SAAS,KAAK,SAAS,IACtD,KAAK,SAAS,SAAS,KAAK,SAAS,KACrC,KAAK;AAAA,IACX;AAEA,YAAQ,gBAAgB,SAAS,cAAe,QAAQ,MAAM;AAC5D,YAAM,QAAQ,QAAQ,SAAS,QAAQ,IAAI;AAC3C,aAAO,KAAK,OAAO,SAAS,KAAK,SAAS,KAAK,KAAK;AAAA,IACtD;AAEA,YAAQ,gBAAgB,SAAS,cAAe,SAAS,IAAI,MAAM;AACjE,YAAM,OAAO,GAAG,QAAQ;AACxB,YAAM,OAAO,GAAG,QAAQ;AACxB,YAAM,QAAQ,QAAQ,SAAS,MAAM,IAAI;AACzC,YAAM,aAAa,KAAK,OAAO,OAAO,KAAK,SAAS,KAAK,KAAK;AAC9D,YAAM,eAAe,KAAK,SAAS;AACnC,YAAM,UAAU,CAAC,KAAK,MAAM,OAAO,KAAK,MAAM,IAAI;AAElD,eAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,iBAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,cAAI,UAAU,IAAI,aAAa,KAAK;AACpC,cAAI,UAAU,KAAK,MAAM;AAEzB,cAAI,KAAK,gBAAgB,KAAK,gBAC5B,IAAI,aAAa,gBAAgB,IAAI,aAAa,cAAc;AAChE,kBAAM,OAAO,KAAK,OAAO,IAAI,gBAAgB,KAAK;AAClD,kBAAM,OAAO,KAAK,OAAO,IAAI,gBAAgB,KAAK;AAClD,sBAAU,QAAQ,KAAK,OAAO,OAAO,IAAI,IAAI,IAAI,CAAC;AAAA,UACpD;AAEA,kBAAQ,QAAQ,IAAI,QAAQ;AAC5B,kBAAQ,QAAQ,IAAI,QAAQ;AAC5B,kBAAQ,QAAQ,IAAI,QAAQ;AAC5B,kBAAQ,MAAM,IAAI,QAAQ;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AClGA;AAAA;AAAA,QAAM,QAAQ;AAEd,aAAS,YAAa,KAAK,QAAQ,MAAM;AACvC,UAAI,UAAU,GAAG,GAAG,OAAO,OAAO,OAAO,MAAM;AAE/C,UAAI,CAAC,OAAO,MAAO,QAAO,QAAQ,CAAC;AACnC,aAAO,SAAS;AAChB,aAAO,QAAQ;AACf,aAAO,MAAM,SAAS,OAAO;AAC7B,aAAO,MAAM,QAAQ,OAAO;AAAA,IAC9B;AAEA,aAAS,mBAAoB;AAC3B,UAAI;AACF,eAAO,SAAS,cAAc,QAAQ;AAAA,MACxC,SAAS,GAAG;AACV,cAAM,IAAI,MAAM,sCAAsC;AAAA,MACxD;AAAA,IACF;AAEA,YAAQ,SAAS,SAAS,OAAQ,QAAQ,QAAQ,SAAS;AACzD,UAAI,OAAO;AACX,UAAI,WAAW;AAEf,UAAI,OAAO,SAAS,gBAAgB,CAAC,UAAU,CAAC,OAAO,aAAa;AAClE,eAAO;AACP,iBAAS;AAAA,MACX;AAEA,UAAI,CAAC,QAAQ;AACX,mBAAW,iBAAiB;AAAA,MAC9B;AAEA,aAAO,MAAM,WAAW,IAAI;AAC5B,YAAM,OAAO,MAAM,cAAc,OAAO,QAAQ,MAAM,IAAI;AAE1D,YAAM,MAAM,SAAS,WAAW,IAAI;AACpC,YAAM,QAAQ,IAAI,gBAAgB,MAAM,IAAI;AAC5C,YAAM,cAAc,MAAM,MAAM,QAAQ,IAAI;AAE5C,kBAAY,KAAK,UAAU,IAAI;AAC/B,UAAI,aAAa,OAAO,GAAG,CAAC;AAE5B,aAAO;AAAA,IACT;AAEA,YAAQ,kBAAkB,SAAS,gBAAiB,QAAQ,QAAQ,SAAS;AAC3E,UAAI,OAAO;AAEX,UAAI,OAAO,SAAS,gBAAgB,CAAC,UAAU,CAAC,OAAO,aAAa;AAClE,eAAO;AACP,iBAAS;AAAA,MACX;AAEA,UAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,YAAM,WAAW,QAAQ,OAAO,QAAQ,QAAQ,IAAI;AAEpD,YAAM,OAAO,KAAK,QAAQ;AAC1B,YAAM,eAAe,KAAK,gBAAgB,CAAC;AAE3C,aAAO,SAAS,UAAU,MAAM,aAAa,OAAO;AAAA,IACtD;AAAA;AAAA;;;AC9DA;AAAA;AAAA,QAAM,QAAQ;AAEd,aAAS,eAAgB,OAAO,QAAQ;AACtC,YAAM,QAAQ,MAAM,IAAI;AACxB,YAAM,MAAM,SAAS,OAAO,MAAM,MAAM;AAExC,aAAO,QAAQ,IACX,MAAM,MAAM,SAAS,eAAe,MAAM,QAAQ,CAAC,EAAE,MAAM,CAAC,IAAI,MAChE;AAAA,IACN;AAEA,aAAS,OAAQ,KAAK,GAAG,GAAG;AAC1B,UAAI,MAAM,MAAM;AAChB,UAAI,OAAO,MAAM,YAAa,QAAO,MAAM;AAE3C,aAAO;AAAA,IACT;AAEA,aAAS,SAAU,MAAM,MAAM,QAAQ;AACrC,UAAI,OAAO;AACX,UAAI,SAAS;AACb,UAAI,SAAS;AACb,UAAI,aAAa;AAEjB,eAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,cAAM,MAAM,KAAK,MAAM,IAAI,IAAI;AAC/B,cAAM,MAAM,KAAK,MAAM,IAAI,IAAI;AAE/B,YAAI,CAAC,OAAO,CAAC,OAAQ,UAAS;AAE9B,YAAI,KAAK,CAAC,GAAG;AACX;AAEA,cAAI,EAAE,IAAI,KAAK,MAAM,KAAK,KAAK,IAAI,CAAC,IAAI;AACtC,oBAAQ,SACJ,OAAO,KAAK,MAAM,QAAQ,MAAM,MAAM,MAAM,IAC5C,OAAO,KAAK,QAAQ,CAAC;AAEzB,qBAAS;AACT,qBAAS;AAAA,UACX;AAEA,cAAI,EAAE,MAAM,IAAI,QAAQ,KAAK,IAAI,CAAC,IAAI;AACpC,oBAAQ,OAAO,KAAK,UAAU;AAC9B,yBAAa;AAAA,UACf;AAAA,QACF,OAAO;AACL;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAEA,YAAQ,SAAS,SAAS,OAAQ,QAAQ,SAAS,IAAI;AACrD,YAAM,OAAO,MAAM,WAAW,OAAO;AACrC,YAAM,OAAO,OAAO,QAAQ;AAC5B,YAAM,OAAO,OAAO,QAAQ;AAC5B,YAAM,aAAa,OAAO,KAAK,SAAS;AAExC,YAAM,KAAK,CAAC,KAAK,MAAM,MAAM,IACzB,KACA,WAAW,eAAe,KAAK,MAAM,OAAO,MAAM,IAClD,cAAc,aAAa,MAAM,aAAa;AAElD,YAAM,OACJ,WAAW,eAAe,KAAK,MAAM,MAAM,QAAQ,IACnD,SAAS,SAAS,MAAM,MAAM,KAAK,MAAM,IAAI;AAE/C,YAAM,UAAU,kBAAuB,aAAa,MAAM,aAAa;AAEvE,YAAM,QAAQ,CAAC,KAAK,QAAQ,KAAK,YAAY,KAAK,QAAQ,eAAe,KAAK,QAAQ;AAEtF,YAAM,SAAS,6CAA6C,QAAQ,UAAU,mCAAmC,KAAK,OAAO;AAE7H,UAAI,OAAO,OAAO,YAAY;AAC5B,WAAG,MAAM,MAAM;AAAA,MACjB;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;;;AChFA;AAAA;AACA,QAAM,aAAa;AAEnB,QAAMC,UAAS;AACf,QAAM,iBAAiB;AACvB,QAAM,cAAc;AAEpB,aAAS,aAAc,YAAY,QAAQ,MAAM,MAAM,IAAI;AACzD,YAAM,OAAO,CAAC,EAAE,MAAM,KAAK,WAAW,CAAC;AACvC,YAAM,UAAU,KAAK;AACrB,YAAM,cAAc,OAAO,KAAK,UAAU,CAAC,MAAM;AAEjD,UAAI,CAAC,eAAe,CAAC,WAAW,GAAG;AACjC,cAAM,IAAI,MAAM,oCAAoC;AAAA,MACtD;AAEA,UAAI,aAAa;AACf,YAAI,UAAU,GAAG;AACf,gBAAM,IAAI,MAAM,4BAA4B;AAAA,QAC9C;AAEA,YAAI,YAAY,GAAG;AACjB,eAAK;AACL,iBAAO;AACP,mBAAS,OAAO;AAAA,QAClB,WAAW,YAAY,GAAG;AACxB,cAAI,OAAO,cAAc,OAAO,OAAO,aAAa;AAClD,iBAAK;AACL,mBAAO;AAAA,UACT,OAAO;AACL,iBAAK;AACL,mBAAO;AACP,mBAAO;AACP,qBAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF,OAAO;AACL,YAAI,UAAU,GAAG;AACf,gBAAM,IAAI,MAAM,4BAA4B;AAAA,QAC9C;AAEA,YAAI,YAAY,GAAG;AACjB,iBAAO;AACP,mBAAS,OAAO;AAAA,QAClB,WAAW,YAAY,KAAK,CAAC,OAAO,YAAY;AAC9C,iBAAO;AACP,iBAAO;AACP,mBAAS;AAAA,QACX;AAEA,eAAO,IAAI,QAAQ,SAAU,SAAS,QAAQ;AAC5C,cAAI;AACF,kBAAM,OAAOA,QAAO,OAAO,MAAM,IAAI;AACrC,oBAAQ,WAAW,MAAM,QAAQ,IAAI,CAAC;AAAA,UACxC,SAAS,GAAG;AACV,mBAAO,CAAC;AAAA,UACV;AAAA,QACF,CAAC;AAAA,MACH;AAEA,UAAI;AACF,cAAM,OAAOA,QAAO,OAAO,MAAM,IAAI;AACrC,WAAG,MAAM,WAAW,MAAM,QAAQ,IAAI,CAAC;AAAA,MACzC,SAAS,GAAG;AACV,WAAG,CAAC;AAAA,MACN;AAAA,IACF;AAEA,YAAQ,SAASA,QAAO;AACxB,YAAQ,WAAW,aAAa,KAAK,MAAM,eAAe,MAAM;AAChE,YAAQ,YAAY,aAAa,KAAK,MAAM,eAAe,eAAe;AAG1E,YAAQ,WAAW,aAAa,KAAK,MAAM,SAAU,MAAM,GAAG,MAAM;AAClE,aAAO,YAAY,OAAO,MAAM,IAAI;AAAA,IACtC,CAAC;AAAA;AAAA;;;ACxED,aAAwB;AAExB,eAAe,eAAe,MAAM,OAAO,CAAC,GAAG;AAC7C,QAAM,OAAO,KAAK,QAAQ;AAC1B,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,uBAAuB,KAAK,wBAAwB;AAC1D,SAAO,MAAa,iBAAU,MAAM,EAAE,OAAO,MAAM,QAAQ,qBAAqB,CAAC;AACnF;AAEA,OAAO,iBAAiB;", + "names": ["module", "require_utils", "QRCode"] +} diff --git a/index.html b/index.html index e339e99..a9ec711 100644 --- a/index.html +++ b/index.html @@ -5,11 +5,11 @@ @@ -63,7 +63,7 @@ - + @@ -85,4227 +85,29 @@ SecureBit.chat - Enhanced Security Edition - - - - + + + - - - - + + + + + - + +
- - + - const slides = [ - { - icon: "fas fa-shield-halved", - color: "orange", - title: "18-Layer Military Security", - description: "Revolutionary defense system with ECDH P-384 + AES-GCM 256 + ECDSA + Complete ASN.1 Validation. Enhanced Security Edition provides military-grade protection exceeding government standards with complete key structure verification." - }, - { - icon: "fas fa-bolt", - color: "yellow", - title: "Lightning Network Payments", - description: "First messenger with Lightning Network integration. Pay-per-session with satoshis via WebLN. Sustainable economic model without ads or data harvesting." - }, - { - icon: "fas fa-network-wired", - color: "purple", - title: "Pure P2P WebRTC Architecture", - description: "Direct peer-to-peer connections without any servers. Impossible to censor, block, or monitor. Complete decentralization with zero infrastructure." - }, - { - icon: "fas fa-sync-alt", - color: "green", - title: "Perfect Forward Secrecy", - description: "Automatic key rotation every 5 minutes or 100 messages. Non-extractable keys with hardware protection ensure past messages remain secure." - }, - { - icon: "fas fa-user-secret", - color: "cyan", - title: "Advanced Traffic Obfuscation", - description: "Fake traffic generation, packet padding, and pattern masking make communication indistinguishable from random noise. Defeats traffic analysis." - }, - { - icon: "fas fa-eye-slash", - color: "blue", - title: "Zero Data Collection", - description: "No registration, no servers, no logs. Messages exist only in browser memory. Complete anonymity with instant anonymous channels." - }, - { - icon: "fas fa-code", - color: "emerald", - title: "100% Open Source Security", - description: "All code is open for audit under MIT license. Uses only standard WebCrypto APIs. Cryptography runs directly in browser without server dependencies." - } - ]; - - const nextSlide = () => setCurrentSlide((prev) => (prev + 1) % slides.length); - const prevSlide = () => setCurrentSlide((prev) => (prev - 1 + slides.length) % slides.length); - const goToSlide = (index) => setCurrentSlide(index); - - React.useEffect(() => { - const timer = setInterval(() => { - nextSlide(); - }, 15000); - return () => clearInterval(timer); - }, []); - - return React.createElement('div', { - className: "mt-12" - }, [ - React.createElement('div', { - key: 'header', - className: "text-center mb-8" - }, [ - React.createElement('h3', { - key: 'title', - className: "text-2xl font-semibold text-primary mb-3" - }, 'Why SecureBit.chat is unique'), - React.createElement('p', { - key: 'subtitle', - className: "text-secondary max-w-2xl mx-auto" - }, 'The only messenger with military-grade cryptography and Lightning payments') - ]), - - React.createElement('div', { - key: 'slider-container', - className: "relative max-w-4xl mx-auto" - }, [ - React.createElement('div', { - key: 'slider-wrapper', - className: "overflow-hidden rounded-xl" - }, [ - React.createElement('div', { - key: 'slides', - className: "flex transition-transform duration-500 ease-in-out", - style: { transform: `translateX(-${currentSlide * 100}%)` } - }, slides.map((slide, index) => - React.createElement('div', { - key: index, - className: "w-full flex-shrink-0 px-4" - }, [ - React.createElement('div', { - key: 'slide-content', - className: "card-minimal rounded-xl p-8 text-center min-h-[300px] flex flex-col justify-center relative overflow-hidden" - }, [ - // Background icon - React.createElement('i', { - key: 'bg-icon', - className: `${slide.icon} absolute right-[-100px] top-1/2 -translate-y-1/2 opacity-10 text-[300px] pointer-events-none ${ - slide.color === 'orange' ? 'text-orange-500' : - slide.color === 'yellow' ? 'text-yellow-500' : - slide.color === 'purple' ? 'text-purple-500' : - slide.color === 'green' ? 'text-green-500' : - slide.color === 'cyan' ? 'text-cyan-500' : - slide.color === 'blue' ? 'text-blue-500' : - 'text-emerald-500' - }` - }), - - // Content - React.createElement('h4', { - key: 'slide-title', - className: "text-xl font-semibold text-primary mb-4 relative z-10" - }, slide.title), - React.createElement('p', { - key: 'slide-description', - className: "text-secondary leading-relaxed max-w-2xl mx-auto relative z-10" - }, slide.description) - ]) - ]) - )) - ]), - - // Navigation - React.createElement('button', { - key: 'prev-btn', - onClick: prevSlide, - className: "absolute left-2 top-1/2 transform -translate-y-1/2 w-10 h-10 bg-gray-600/80 hover:bg-gray-500/80 text-white rounded-full flex items-center justify-center transition-all duration-200 z-10" - }, [ - React.createElement('i', { - key: 'prev-icon', - className: "fas fa-chevron-left" - }) - ]), - React.createElement('button', { - key: 'next-btn', - onClick: nextSlide, - className: "absolute right-2 top-1/2 transform -translate-y-1/2 w-10 h-10 bg-gray-600/80 hover:bg-gray-500/80 text-white rounded-full flex items-center justify-center transition-all duration-200 z-10" - }, [ - React.createElement('i', { - key: 'next-icon', - className: "fas fa-chevron-right" - }) - ]) - ]), - - // Enhanced dots navigation (оставляем улучшенные точки) - React.createElement('div', { - key: 'dots-container', - className: "flex justify-center space-x-3 mt-6" - }, slides.map((slide, index) => - React.createElement('button', { - key: index, - onClick: () => goToSlide(index), - className: `relative group transition-all duration-300 ${ - index === currentSlide - ? 'w-12 h-4 bg-orange-500 rounded-full' - : 'w-4 h-4 bg-gray-600 hover:bg-gray-500 rounded-full hover:scale-125' - }` - }, [ - // Tooltip on hover - React.createElement('div', { - key: 'tooltip', - className: "absolute -top-10 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white text-xs px-2 py-1 rounded opacity-0 group-hover:opacity-100 transition-opacity duration-200 whitespace-nowrap pointer-events-none" - }, slide.title) - ]) - )) - ]); -}; - - - - const ComparisonTable = () => { - const [selectedFeature, setSelectedFeature] = React.useState(null); - - const messengers = [ - { - name: "SecureBit.chat", - logo:
- -
, - type: "P2P WebRTC", - version: "Latest", - color: "orange", - }, - { - name: "Signal", - logo: ( - - - - - ), - type: "Centralized", - version: "Latest", - color: "blue", - }, - { - name: "Threema", - logo: ( - - - - - - - - ), - type: "Centralized", - version: "Latest", - color: "green", - }, - { - name: "Session", - logo: ( - - - - - ), - type: "Onion Network", - version: "Latest", - color: "cyan", - }, - ]; - - const features = [ - { - name: "Security Architecture", - lockbit: { status: "🏆", detail: "18-layer military-grade defense system with complete ASN.1 validation" }, - signal: { status: "✅", detail: "Signal Protocol with double ratchet" }, - threema: { status: "✅", detail: "Standard security implementation" }, - session: { status: "✅", detail: "Modified Signal Protocol + Onion routing" }, - }, - { - name: "Cryptography", - lockbit: { status: "🏆", detail: "ECDH P-384 + AES-GCM 256 + ECDSA P-384" }, - signal: { status: "✅", detail: "Signal Protocol + Double Ratchet" }, - threema: { status: "✅", detail: "NaCl + XSalsa20 + Poly1305" }, - session: { status: "✅", detail: "Modified Signal Protocol" }, - }, - { - name: "Perfect Forward Secrecy", - lockbit: { status: "🏆", detail: "Auto rotation every 5 minutes or 100 messages" }, - signal: { status: "✅", detail: "Double Ratchet algorithm" }, - threema: { status: "⚠️", detail: "Partial (group chats)" }, - session: { status: "✅", detail: "Session Ratchet algorithm" }, - }, - { - name: "Architecture", - lockbit: { status: "🏆", detail: "Pure P2P WebRTC without servers" }, - signal: { status: "❌", detail: "Centralized Signal servers" }, - threema: { status: "❌", detail: "Threema servers in Switzerland" }, - session: { status: "⚠️", detail: "Onion routing via network nodes" }, - }, - { - name: "Registration Anonymity", - lockbit: { status: "🏆", detail: "No registration required, instant anonymous channels" }, - signal: { status: "❌", detail: "Phone number required" }, - threema: { status: "✅", detail: "ID generated locally" }, - session: { status: "✅", detail: "Random session ID" }, - }, - { - name: "Payment Integration", - lockbit: { status: "🏆", detail: "Lightning Network satoshis per session + WebLN" }, - signal: { status: "❌", detail: "No payment system" }, - threema: { status: "❌", detail: "No payment system" }, - session: { status: "❌", detail: "No payment system" }, - }, - { - name: "Metadata Protection", - lockbit: { status: "🏆", detail: "Full metadata encryption + traffic obfuscation" }, - signal: { status: "⚠️", detail: "Sealed Sender (partial)" }, - threema: { status: "⚠️", detail: "Minimal metadata" }, - session: { status: "✅", detail: "Onion routing hides metadata" }, - }, - { - name: "Traffic Obfuscation", - lockbit: { status: "🏆", detail: "Fake traffic + pattern masking + packet padding" }, - signal: { status: "❌", detail: "No traffic obfuscation" }, - threema: { status: "❌", detail: "No traffic obfuscation" }, - session: { status: "✅", detail: "Onion routing provides obfuscation" }, - }, - { - name: "Open Source", - lockbit: { status: "🏆", detail: "100% open + auditable + MIT license" }, - signal: { status: "✅", detail: "Fully open" }, - threema: { status: "⚠️", detail: "Only clients open" }, - session: { status: "✅", detail: "Fully open" }, - }, - { - name: "MITM Protection", - lockbit: { status: "🏆", detail: "Out-of-band verification + mutual auth + ECDSA" }, - signal: { status: "✅", detail: "Safety numbers verification" }, - threema: { status: "✅", detail: "QR code scanning" }, - session: { status: "⚠️", detail: "Basic key verification" }, - }, - { - name: "Economic Model", - lockbit: { status: "🏆", detail: "Sustainable pay-per-session model" }, - signal: { status: "⚠️", detail: "Donations and grants dependency" }, - threema: { status: "✅", detail: "One-time app purchase" }, - session: { status: "⚠️", detail: "Donations dependency" }, - }, - { - name: "Censorship Resistance", - lockbit: { status: "🏆", detail: "Impossible to block P2P + no servers to target" }, - signal: { status: "⚠️", detail: "Blocked in authoritarian countries" }, - threema: { status: "⚠️", detail: "May be blocked" }, - session: { status: "✅", detail: "Onion routing bypasses blocks" }, - }, - { - name: "Data Storage", - lockbit: { status: "🏆", detail: "Zero data storage - only in browser memory" }, - signal: { status: "⚠️", detail: "Local database storage" }, - threema: { status: "⚠️", detail: "Local + optional backup" }, - session: { status: "⚠️", detail: "Local database storage" }, - }, - { - name: "Key Security", - lockbit: { status: "🏆", detail: "Non-extractable keys + hardware protection" }, - signal: { status: "✅", detail: "Secure key storage" }, - threema: { status: "✅", detail: "Local key storage" }, - session: { status: "✅", detail: "Secure key storage" }, - }, - { - name: "Post-Quantum Roadmap", - lockbit: { status: "✅", detail: "Planned v5.0 - CRYSTALS-Kyber/Dilithium" }, - signal: { status: "⚠️", detail: "PQXDH in development" }, - threema: { status: "❌", detail: "Not announced" }, - session: { status: "❌", detail: "Not announced" }, - }, - ]; - - const getStatusIcon = (status) => { - const statusMap = { - "🏆": { icon: "🏆", color: "text-yellow-400" }, - "✅": { icon: "✅", color: "text-green-400" }, - "⚠️": { icon: "⚠️", color: "text-yellow-400" }, - "❌": { icon: "❌", color: "text-red-400" }, - }; - return statusMap[status] || { icon: status, color: "text-gray-400" }; - }; - - const toggleFeatureDetail = (index) => { - setSelectedFeature(selectedFeature === index ? null : index); - }; - - return ( -
- {/* Title */} -
-

- Enhanced Security Edition Comparison -

-

- Enhanced Security Edition vs leading secure messengers -

-
- 🏆 - - Category Leader - Military-Grade Security - -
-
- - {/* Table container */} -
- {/* Mobile Alert */} -
-

- 💡 Rotate your device horizontally for better viewing -

-
- - {/* Table */} -
- - {/* Table Header */} - - - - {messengers.map((messenger, index) => ( - - ))} - - - - {/* Table body*/} - - {features.map((feature, featureIndex) => ( - - toggleFeatureDetail(featureIndex)} - > - - - - - - - - {/* Details */} - {selectedFeature === featureIndex && ( - - - - - - - - )} - - ))} - -
- Security Criterion - -
-
{messenger.logo}
-
- {messenger.name} -
-
{messenger.type}
-
{messenger.version}
-
-
-
- {feature.name} - -
-
- - {getStatusIcon(feature.lockbit.status).icon} - - - - {getStatusIcon(feature.signal.status).icon} - - - - {getStatusIcon(feature.threema.status).icon} - - - - {getStatusIcon(feature.session.status).icon} - -
Technical Details: -
- {feature.lockbit.detail} -
-
-
- {feature.signal.detail} -
-
-
- {feature.threema.detail} -
-
-
- {feature.session.detail} -
-
-
- - {/* Legend */} -
-
- 🏆 - Category Leader -
-
- - Excellent -
-
- ⚠️ - Partial/Limited -
-
- - Not Available -
-
- - {/* Legend */} -
-
-

- - SecureBit.chat Enhanced Security Edition Summary -

-

- SecureBit.chat dominates in 11 out of 15 security categories, establishing itself as the most secure P2P messenger available. - The Enhanced Security Edition introduces revolutionary 18-layer defense architecture with complete ASN.1 validation, Lightning Network integration, and military-grade cryptography that exceeds government and enterprise standards. -

-
-
-
🔐 Cryptographic Superiority
-

- ECDH P-384 + AES-GCM 256 + ECDSA P-384 + Complete ASN.1 Validation with non-extractable keys and 18-layer defense system -

-
-
-
⚡ Lightning Integration
-

- First messenger with Lightning Network payments - sustainable economic model with instant satoshi transactions -

-
-
-
🌐 True P2P Architecture
-

- Pure WebRTC connections with zero servers, impossible to censor or shutdown, complete anonymity -

-
-
-
🎭 Traffic Obfuscation
-

- Advanced fake traffic generation, packet padding, and pattern masking defeat traffic analysis -

-
-
-
-
- - {/* Version information */} -
-
- 🚀 - Enhanced Security Edition v4.02.985 - ECDH + DTLS + SAS - - Active Production Release - | Next: v5.0 Post-Quantum -
-
-
-
- ); - }; - - function Roadmap() { - const [selectedPhase, setSelectedPhase] = React.useState(null); - const phases = [ - { - version: "v1.0", - title: "Start of Development", - status: "done", - date: "Early 2025", - description: "Idea, prototype, and infrastructure setup", - features: [ - "Concept and requirements formation", - "Stack selection: WebRTC, P2P, cryptography", - "First messaging prototypes", - "Repository creation and CI", - "Basic encryption architecture", - "UX/UI design" - ] - }, - { - version: "v1.5", - title: "Alpha Release", - status: "done", - date: "Spring 2025", - description: "First public alpha: basic chat and key exchange", - features: [ - "Basic P2P messaging via WebRTC", - "Simple E2E encryption (demo scheme)", - "Stable signaling and reconnection", - "Minimal UX for testing", - "Feedback collection from early testers" - ] - }, - { - version: "v2.0", - title: "Security Hardened", - status: "done", - date: "Summer 2025", - description: "Security strengthening and stable branch release", - features: [ - "ECDH/ECDSA implementation in production", - "Perfect Forward Secrecy and key rotation", - "Improved authentication checks", - "File encryption and large payload transfers", - "Audit of basic cryptoprocesses" - ] - }, - { - version: "v3.0", - title: "Scaling & Stability", - status: "done", - date: "Fall 2025", - description: "Network scaling and stability improvements", - features: [ - "Optimization of P2P connections and NAT traversal", - "Reconnection mechanisms and message queues", - "Reduced battery consumption on mobile", - "Support for multi-device synchronization", - "Monitoring and logging tools for developers" - ] - }, - { - version: "v3.5", - title: "Privacy-first Release", - status: "done", - date: "Winter 2025", - description: "Focus on privacy: minimizing metadata", - features: [ - "Metadata protection and fingerprint reduction", - "Experiments with onion routing and DHT", - "Options for anonymous connections", - "Preparation for open code audit", - "Improved user verification processes" - ] - }, - - // current and future phases - { - version: "v4.02.985", - title: "Enhanced Security Edition", - status: "current", - date: "Now", - description: "Current version with ECDH + DTLS + SAS security, 18-layer military-grade cryptography and complete ASN.1 validation", - features: [ - "ECDH + DTLS + SAS triple-layer security", - "ECDH P-384 + AES-GCM 256-bit encryption", - "DTLS fingerprint verification", - "SAS (Short Authentication String) verification", - "Perfect Forward Secrecy with key rotation", - "Enhanced MITM attack prevention", - "Complete ASN.1 DER validation", - "OID and EC point verification", - "SPKI structure validation", - "Lightning Network payments", - "P2P WebRTC architecture", - "Metadata protection", - "100% open source code" - ] - }, - { - version: "v4.5", - title: "Mobile & Desktop Edition", - status: "development", - date: "Q2 2025", - description: "Native apps for all platforms", - features: [ - "PWA app for mobile", - "Electron app for desktop", - "Real-time notifications", - "Automatic reconnection", - "Battery optimization", - "Cross-device synchronization", - "Improved UX/UI", - "Support for files up to 100MB" - ] - }, - { - version: "v5.0", - title: "Quantum-Resistant Edition", - status: "planned", - date: "Q4 2025", - description: "Protection against quantum computers", - features: [ - "Post-quantum cryptography CRYSTALS-Kyber", - "SPHINCS+ digital signatures", - "Hybrid scheme: classic + PQ", - "Quantum-safe key exchange", - "Updated hashing algorithms", - "Migration of existing sessions", - "Compatibility with v4.x", - "Quantum-resistant protocols" - ] - }, - { - version: "v5.5", - title: "Group Communications", - status: "planned", - date: "Q2 2026", - description: "Group chats with preserved privacy", - features: [ - "P2P group connections up to 8 participants", - "Mesh networking for groups", - "Signal Double Ratchet for groups", - "Anonymous groups without metadata", - "Ephemeral groups (disappear after session)", - "Group Lightning payments", - "Cryptographic group administration", - "Group member auditing" - ] - }, - { - version: "v6.0", - title: "Decentralized Network", - status: "research", - date: "2027", - description: "Fully decentralized network", - features: [ - "LockBit node mesh network", - "DHT for peer discovery", - "Built-in onion routing", - "Tokenomics and node incentives", - "Governance via DAO", - "Interoperability with other networks", - "Cross-platform compatibility", - "Self-healing network" - ] - }, - { - version: "v7.0", - title: "AI Privacy Assistant", - status: "research", - date: "2028+", - description: "AI for privacy and security", - features: [ - "Local AI threat analysis", - "Automatic MITM detection", - "Adaptive cryptography", - "Personalized security recommendations", - "Zero-knowledge machine learning", - "Private AI assistant", - "Predictive security", - "Autonomous attack protection" - ] - } - ]; - - - const getStatusConfig = (status) => { - switch (status) { - case 'current': - return { - color: 'green', - bgClass: 'bg-green-500/10 border-green-500/20', - textClass: 'text-green-400', - icon: 'fas fa-check-circle', - label: 'Current Version' - }; - case 'development': - return { - color: 'orange', - bgClass: 'bg-orange-500/10 border-orange-500/20', - textClass: 'text-orange-400', - icon: 'fas fa-code', - label: 'In Development' - }; - case 'planned': - return { - color: 'blue', - bgClass: 'bg-blue-500/10 border-blue-500/20', - textClass: 'text-blue-400', - icon: 'fas fa-calendar-alt', - label: 'Planned' - }; - case 'research': - return { - color: 'purple', - bgClass: 'bg-purple-500/10 border-purple-500/20', - textClass: 'text-purple-400', - icon: 'fas fa-flask', - label: 'Research' - }; - case 'done': - return { - color: 'gray', - bgClass: 'bg-gray-500/10 border-gray-500/20', - textClass: 'text-gray-300', - icon: 'fas fa-flag-checkered', - label: 'Released' - }; - default: - return { - color: 'gray', - bgClass: 'bg-gray-500/10 border-gray-500/20', - textClass: 'text-gray-400', - icon: 'fas fa-question', - label: 'Unknown' - }; - } - }; - - - const togglePhaseDetail = (index) => { - setSelectedPhase(selectedPhase === index ? null : index); - }; - return ( -
-
-

- Development Roadmap -

-

- Evolution of SecureBit.chat : from initial development to quantum-resistant decentralized network with complete ASN.1 validation -

-
- - - Click on a version for details - -
-
- -
-
- {/* The line has been removed */} - -
- {phases.map((phase, index) => { - const statusConfig = getStatusConfig(phase.status); - const isExpanded = selectedPhase === index; - - return ( -
- {/* The dots are visible only on sm and larger screens */} - - -
- ); - })} -
-
-
- -
-
-

- Join the future of privacy -

-

- SecureBit.chat grows thanks to the community. Your ideas and feedback help shape the future of secure communication with complete ASN.1 validation. -

- - -
-
-
- ); - } - - - // Enhanced Copy Button with better UX - const EnhancedCopyButton = ({ text, className = "", children }) => { - const [copied, setCopied] = React.useState(false); - - const handleCopy = async () => { - try { - await navigator.clipboard.writeText(text); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } catch (error) { - console.error('Copy failed:', error); - // Fallback for older browsers - const textArea = document.createElement('textarea'); - textArea.value = text; - document.body.appendChild(textArea); - textArea.select(); - document.execCommand('copy'); - document.body.removeChild(textArea); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } - }; - - return React.createElement('button', { - onClick: handleCopy, - className: `${className} transition-all duration-200` - }, [ - React.createElement('i', { - key: 'icon', - className: `${copied ? 'fas fa-check accent-green' : 'fas fa-copy text-secondary'} mr-2` - }), - copied ? 'Copied!' : children - ]); - }; - - // Verification Component - const VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, remoteConfirmed, bothConfirmed }) => { - return React.createElement('div', { - className: "card-minimal rounded-xl p-6 border-purple-500/20" - }, [ - React.createElement('div', { - key: 'header', - className: "flex items-center mb-4" - }, [ - React.createElement('div', { - key: 'icon', - className: "w-10 h-10 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mr-3" - }, [ - React.createElement('i', { - className: 'fas fa-shield-alt accent-purple' - }) - ]), - React.createElement('h3', { - key: 'title', - className: "text-lg font-medium text-primary" - }, "Security verification") - ]), - React.createElement('div', { - key: 'content', - className: "space-y-4" - }, [ - React.createElement('p', { - key: 'description', - className: "text-secondary text-sm" - }, "Verify the security code with your contact via another communication channel (voice, SMS, etc.):"), - React.createElement('div', { - key: 'code-display', - className: "text-center" - }, [ - React.createElement('div', { - key: 'code', - className: "verification-code text-2xl py-4" - }, verificationCode) - ]), - // Verification status indicators - React.createElement('div', { - key: 'verification-status', - className: "space-y-2" - }, [ - React.createElement('div', { - key: 'local-status', - className: `flex items-center justify-between p-2 rounded-lg ${localConfirmed ? 'bg-green-500/10 border border-green-500/20' : 'bg-gray-500/10 border border-gray-500/20'}` - }, [ - React.createElement('span', { - key: 'local-label', - className: "text-sm text-secondary" - }, "Your confirmation:"), - React.createElement('div', { - key: 'local-indicator', - className: "flex items-center" - }, [ - React.createElement('i', { - key: 'local-icon', - className: `fas ${localConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2` - }), - React.createElement('span', { - key: 'local-text', - className: `text-sm ${localConfirmed ? 'text-green-400' : 'text-gray-400'}` - }, localConfirmed ? 'Confirmed' : 'Pending') - ]) - ]), - React.createElement('div', { - key: 'remote-status', - className: `flex items-center justify-between p-2 rounded-lg ${remoteConfirmed ? 'bg-green-500/10 border border-green-500/20' : 'bg-gray-500/10 border border-gray-500/20'}` - }, [ - React.createElement('span', { - key: 'remote-label', - className: "text-sm text-secondary" - }, "Peer confirmation:"), - React.createElement('div', { - key: 'remote-indicator', - className: "flex items-center" - }, [ - React.createElement('i', { - key: 'remote-icon', - className: `fas ${remoteConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2` - }), - React.createElement('span', { - key: 'remote-text', - className: `text-sm ${remoteConfirmed ? 'text-green-400' : 'text-gray-400'}` - }, remoteConfirmed ? 'Confirmed' : 'Pending') - ]) - ]) - ]), - React.createElement('div', { - key: 'warning', - className: "p-3 bg-yellow-500/10 border border-yellow-500/20 rounded-lg" - }, [ - React.createElement('p', { - className: "text-yellow-400 text-sm flex items-center" - }, [ - React.createElement('i', { - className: 'fas fa-exclamation-triangle mr-2' - }), - 'Make sure the codes match exactly.!' - ]) - ]), - React.createElement('div', { - key: 'buttons', - className: "flex space-x-3" - }, [ - React.createElement('button', { - key: 'confirm', - onClick: onConfirm, - disabled: localConfirmed, - className: `flex-1 py-3 px-4 rounded-lg font-medium transition-all duration-200 ${localConfirmed ? 'bg-gray-500/20 text-gray-400 cursor-not-allowed' : 'btn-verify text-white'}` - }, [ - React.createElement('i', { - className: `fas ${localConfirmed ? 'fa-check-circle' : 'fa-check'} mr-2` - }), - localConfirmed ? 'Confirmed' : 'The codes match' - ]), - React.createElement('button', { - key: 'reject', - onClick: onReject, - className: "flex-1 bg-red-500/10 hover:bg-red-500/20 text-red-400 border border-red-500/20 py-3 px-4 rounded-lg font-medium transition-all duration-200" - }, [ - React.createElement('i', { - className: 'fas fa-times mr-2' - }), - 'The codes do not match' - ]) - ]) - ]) - ]); - }; - - // Enhanced Chat Message with better security indicators - const EnhancedChatMessage = ({ message, type, timestamp }) => { - const formatTime = (ts) => { - return new Date(ts).toLocaleTimeString('ru-RU', { - hour: '2-digit', - minute: '2-digit', - second: '2-digit' - }); - }; - - const getMessageStyle = () => { - switch (type) { - case 'sent': - return { - container: "ml-auto bg-orange-500/15 border-orange-500/20 text-primary", - icon: "fas fa-lock accent-orange", - label: "Encrypted" - }; - case 'received': - return { - container: "mr-auto card-minimal text-primary", - icon: "fas fa-unlock-alt accent-green", - label: "Decrypted" - }; - case 'system': - return { - container: "mx-auto bg-yellow-500/10 border border-yellow-500/20 text-yellow-400", - icon: "fas fa-info-circle accent-yellow", - label: "System" - }; - default: - return { - container: "mx-auto card-minimal text-secondary", - icon: "fas fa-circle text-muted", - label: "Unknown" - }; - } - }; - - const style = getMessageStyle(); - - return React.createElement('div', { - className: `message-slide mb-3 p-3 rounded-lg max-w-md break-words ${style.container} border` - }, [ - React.createElement('div', { - key: 'content', - className: "flex items-start space-x-2" - }, [ - React.createElement('i', { - key: 'icon', - className: `${style.icon} text-sm mt-0.5 opacity-70` - }), - React.createElement('div', { - key: 'text', - className: "flex-1" - }, [ - React.createElement('div', { - key: 'message', - className: "text-sm" - }, message), - timestamp && React.createElement('div', { - key: 'meta', - className: "flex items-center justify-between mt-1 text-xs opacity-50" - }, [ - React.createElement('span', { - key: 'time' - }, formatTime(timestamp)), - React.createElement('span', { - key: 'status', - className: "text-xs" - }, style.label) - ]) - ]) - ]) - ]); - }; - - // Enhanced Connection Setup with verification - const EnhancedConnectionSetup = ({ - messages, - onCreateOffer, - onCreateAnswer, - onConnect, - onClearData, - onVerifyConnection, - connectionStatus, - offerData, - answerData, - offerInput, - setOfferInput, - answerInput, - setAnswerInput, - showOfferStep, - showAnswerStep, - verificationCode, - showVerification, - offerPassword, - answerPassword, - localVerificationConfirmed, - remoteVerificationConfirmed, - bothVerificationsConfirmed - }) => { - const [mode, setMode] = React.useState('select'); - - const resetToSelect = () => { - setMode('select'); - onClearData(); - }; - - const handleVerificationConfirm = () => { - onVerifyConnection(true); - }; - - const handleVerificationReject = () => { - onVerifyConnection(false); - }; - - if (showVerification) { - return React.createElement('div', { - className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" - }, [ - React.createElement('div', { - key: 'verification', - className: "w-full max-w-md" - }, [ - React.createElement(VerificationStep, { - verificationCode: verificationCode, - onConfirm: handleVerificationConfirm, - onReject: handleVerificationReject, - localConfirmed: localVerificationConfirmed, - remoteConfirmed: remoteVerificationConfirmed, - bothConfirmed: bothVerificationsConfirmed - }) - ]) - ]); - } - - if (mode === 'select') { - return React.createElement('div', { - className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" - }, [ - React.createElement('div', { - key: 'selector', - className: "w-full max-w-4xl" - }, [ - React.createElement('div', { - key: 'header', - className: "text-center mb-8" - }, [ - React.createElement('h2', { - key: 'title', - className: "text-2xl font-semibold text-primary mb-3" - }, 'Start secure communication'), - React.createElement('p', { - key: 'subtitle', - className: "text-secondary max-w-2xl mx-auto" - }, "Choose a connection method for a secure channel with ECDH encryption and Perfect Forward Secrecy.") - ]), - - React.createElement('div', { - key: 'options', - className: "grid md:grid-cols-2 gap-6 max-w-3xl mx-auto" - }, [ - // Create Connection - React.createElement('div', { - key: 'create', - onClick: () => setMode('create'), - className: "card-minimal rounded-xl p-6 cursor-pointer group" - }, [ - React.createElement('div', { - key: 'icon', - className: "w-12 h-12 bg-blue-500/10 border border-blue-500/20 rounded-lg flex items-center justify-center mx-auto mb-4" - }, [ - React.createElement('i', { - className: 'fas fa-plus text-xl text-blue-400' - }) - ]), - React.createElement('h3', { - key: 'title', - className: "text-lg font-semibold text-primary text-center mb-3" - }, "Create channel"), - React.createElement('p', { - key: 'description', - className: "text-secondary text-center text-sm mb-4" - }, "Initiate a new secure connection with encrypted exchange"), - React.createElement('div', { - key: 'features', - className: "space-y-2" - }, [ - React.createElement('div', { - key: 'f1', - className: "flex items-center text-sm text-muted" - }, [ - React.createElement('i', { - className: 'fas fa-key accent-orange mr-2 text-xs' - }), - 'Generating ECDH keys' - ]), - React.createElement('div', { - key: 'f2', - className: "flex items-center text-sm text-muted" - }, [ - React.createElement('i', { - className: 'fas fa-shield-alt accent-orange mr-2 text-xs' - }), - 'Verification code' - ]), - React.createElement('div', { - key: 'f3', - className: "flex items-center text-sm text-muted" - }, [ - React.createElement('i', { - className: 'fas fa-sync-alt accent-purple mr-2 text-xs' - }), - 'PFS key rotation' - ]) - ]) - ]), - - // Join Connection - React.createElement('div', { - key: 'join', - onClick: () => setMode('join'), - className: "card-minimal rounded-xl p-6 cursor-pointer group" - }, [ - React.createElement('div', { - key: 'icon', - className: "w-12 h-12 bg-green-500/10 border border-green-500/20 rounded-lg flex items-center justify-center mx-auto mb-4" - }, [ - React.createElement('i', { - className: 'fas fa-link text-xl accent-green' - }) - ]), - React.createElement('h3', { - key: 'title', - className: "text-lg font-semibold text-primary text-center mb-3" - }, "Join"), - React.createElement('p', { - key: 'description', - className: "text-secondary text-center text-sm mb-4" - }, "Connect to an existing secure channel"), - React.createElement('div', { - key: 'features', - className: "space-y-2" - }, [ - React.createElement('div', { - key: 'f1', - className: "flex items-center text-sm text-muted" - }, [ - React.createElement('i', { - className: 'fas fa-paste accent-green mr-2 text-xs' - }), - 'Paste Offer invitation' - ]), - React.createElement('div', { - key: 'f2', - className: "flex items-center text-sm text-muted" - }, [ - React.createElement('i', { - className: 'fas fa-check-circle accent-green mr-2 text-xs' - }), - 'Automatic verification' - ]), - React.createElement('div', { - key: 'f3', - className: "flex items-center text-sm text-muted" - }, [ - React.createElement('i', { - className: 'fas fa-sync-alt accent-purple mr-2 text-xs' - }), - 'PFS protection' - ]) - ]) - ]) - ]), - - - React.createElement('div', { - key: 'security-features', - className: "grid grid-cols-2 md:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4 max-w-6xl mx-auto mt-8" - }, [ - React.createElement('div', { key: 'feature1', className: "text-center p-3 sm:p-4" }, [ - React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-green-500/10 border border-green-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ - React.createElement('i', { className: 'fas fa-key accent-green' }) - ]), - React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "ECDH P-384 Key Exchange"), - React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Military-grade elliptic curve key exchange") - ]), - React.createElement('div', { key: 'feature2', className: "text-center p-3 sm:p-4" }, [ - React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ - React.createElement('i', { className: 'fas fa-user-shield accent-purple' }) - ]), - React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "MITM Protection"), - React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Out-of-band verification against attacks") - ]), - React.createElement('div', { key: 'feature3', className: "text-center p-3 sm:p-4" }, [ - React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-orange-500/10 border border-orange-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ - React.createElement('i', { className: 'fas fa-lock accent-orange' }) - ]), - React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "AES-GCM 256 Encryption"), - React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Authenticated encryption standard") - ]), - React.createElement('div', { key: 'feature4', className: "text-center p-3 sm:p-4" }, [ - React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-cyan-500/10 border border-cyan-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ - React.createElement('i', { className: 'fas fa-sync-alt accent-cyan' }) - ]), - React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "Perfect Forward Secrecy"), - React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Automatic key rotation every 5 minutes") - ]), - React.createElement('div', { key: 'feature5', className: "text-center p-3 sm:p-4" }, [ - React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-blue-500/10 border border-blue-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ - React.createElement('i', { className: 'fas fa-signature accent-blue' }) - ]), - React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "ECDSA P-384 Signatures"), - React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Digital signatures for message integrity") - ]), - React.createElement('div', { key: 'feature6', className: "text-center p-3 sm:p-4" }, [ - React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-yellow-500/10 border border-yellow-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ - React.createElement('i', { className: 'fas fa-bolt accent-yellow' }) - ]), - React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "Lightning Payments"), - React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Pay-per-session via WebLN") - ]) - ]), - - // Wallet Logos Section - React.createElement('div', { - key: 'wallet-logos-section', - className: "mt-8" - }, [ - React.createElement('div', { - key: 'wallet-logos-header', - className: "text-center mb-4" - }, [ - React.createElement('h3', { - key: 'title', - className: "text-lg font-medium text-primary mb-2" - }, "Supported Lightning wallets"), - React.createElement('p', { - key: 'subtitle', - className: "text-secondary text-sm" - }, "To pay for sessions, use any of the popular wallets.") - ]), - React.createElement('div', { - key: 'wallet-logos-container', - className: "wallet-logos-container" - }, [ - React.createElement('div', { - key: 'wallet-logos-track', - className: "wallet-logos-track" - }, [ - // First set of logos - React.createElement('a', { - key: 'alby1-link', - href: "https://getalby.com", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo alby" - }, [ - React.createElement('img', { - key: 'alby-img1', - src: "logo/alby.svg", - alt: "Alby Lightning Wallet", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'zeus1-link', - href: "https://zeusln.app", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo zeus" - }, [ - React.createElement('img', { - key: 'zeus-img1', - src: "logo/zeus.svg", - alt: "Zeus Lightning Wallet", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'wos1-link', - href: "https://www.walletofsatoshi.com", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo wos" - }, [ - React.createElement('img', { - key: 'wos-img1', - src: "logo/wos.svg", - alt: "Wallet of Satoshi", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'muun1-link', - href: "https://muun.com", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo muun" - }, [ - React.createElement('img', { - key: 'muun-img1', - src: "logo/muun.svg", - alt: "Muun Wallet", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'atomic1-link', - href: "https://atomicwallet.io", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo atomic" - }, [ - React.createElement('img', { - key: 'atomic-img1', - src: "logo/atomic.svg", - alt: "Atomic Wallet", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'breez1-link', - href: "https://breez.technology/mobile/", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo breez" - }, [ - React.createElement('img', { - key: 'breez-img1', - src: "logo/breez.svg", - alt: "Breez Lightning Wallet", - }) - ]), - React.createElement('a', { - key: 'lightning-labs1-link', - href: "https://lightning.engineering", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo lightning-labs" - }, [ - React.createElement('img', { - key: 'lightning-labs-img1', - src: "logo/lightning-labs.svg", - alt: "Lightning Labs", - }) - ]), - React.createElement('a', { - key: 'lnbits1-link', - href: "https://lnbits.com", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo lnbits" - }, [ - React.createElement('img', { - key: 'lnbits-img1', - src: "logo/lnbits.svg", - alt: "LNbits", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'strike1-link', - href: "https://strike.me", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo strike" - }, [ - React.createElement('img', { - key: 'strike-img1', - src: "logo/strike.svg", - alt: "Strike", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'impervious1-link', - href: "https://impervious.ai", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo impervious" - }, [ - React.createElement('img', { - key: 'impervious-img1', - src: "logo/impervious.svg", - alt: "Impervious", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'bitcoin-lightning1-link', - href: "https://www.blink.sv/", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo bitcoin-lightning" - }, [ - React.createElement('img', { - key: 'blink-img1', - src: "logo/blink.svg", - alt: "Blink Wallet", - className: "wallet-logo-img" - }) - ]), - // Second set of logos - React.createElement('a', { - key: 'alby2-link', - href: "https://getalby.com", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo alby" - }, [ - React.createElement('img', { - key: 'alby-img2', - src: "logo/alby.svg", - alt: "Alby Lightning Wallet", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'zeus2-link', - href: "https://zeusln.app", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo zeus" - }, [ - React.createElement('img', { - key: 'zeus-img2', - src: "logo/zeus.svg", - alt: "Zeus Lightning Wallet", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'wos2-link', - href: "https://www.walletofsatoshi.com", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo wos" - }, [ - React.createElement('img', { - key: 'wos-img2', - src: "logo/wos.svg", - alt: "Wallet of Satoshi", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'muun2-link', - href: "https://muun.com", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo muun" - }, [ - React.createElement('img', { - key: 'muun-img2', - src: "logo/muun.svg", - alt: "Muun Wallet", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'atomic2-link', - href: "https://atomicwallet.io", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo atomic" - }, [ - React.createElement('img', { - key: 'atomic-img2', - src: "logo/atomic.svg", - alt: "Atomic Wallet", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'breez2-link', - href: "https://breez.technology/mobile/", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo breez" - }, [ - React.createElement('img', { - key: 'breez-img2', - src: "logo/breez.svg", - alt: "Breez Lightning Wallet", - }) - ]), - React.createElement('a', { - key: 'lightning-labs2-link', - href: "https://lightning.engineering", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo lightning-labs" - }, [ - React.createElement('img', { - key: 'lightning-labs-img2', - src: "logo/lightning-labs.svg", - alt: "Lightning Labs", - }) - ]), - React.createElement('a', { - key: 'lnbits2-link', - href: "https://lnbits.com", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo lnbits" - }, [ - React.createElement('img', { - key: 'lnbits-img2', - src: "logo/lnbits.svg", - alt: "LNbits", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'strike2-link', - href: "https://strike.me", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo strike" - }, [ - React.createElement('img', { - key: 'strike-img2', - src: "logo/strike.svg", - alt: "Strike", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'impervious2-link', - href: "https://impervious.ai", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo impervious" - }, [ - React.createElement('img', { - key: 'impervious-img2', - src: "logo/impervious.svg", - alt: "Impervious", - className: "wallet-logo-img" - }) - ]), - React.createElement('a', { - key: 'bitcoin-lightning2-link', - href: "https://www.blink.sv/", - target: "_blank", - rel: "noindex nofollow", - className: "wallet-logo bitcoin-lightning" - }, [ - React.createElement('img', { - key: 'blink-img2', - src: "logo/blink.svg", - alt: "Blink Wallet", - className: "wallet-logo-img" - }) - ]) - ]) - ]) - ]), - React.createElement(UniqueFeatureSlider, { key: 'unique-features-slider' }), - - React.createElement(DownloadApps, { key: 'download-apps' }), - - React.createElement(ComparisonTable, { key: 'comparison-table' }), - - React.createElement(Roadmap, { key: 'roadmap' }), - ]) - ]); - } - - if (mode === 'create') { - return React.createElement('div', { - className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" - }, [ - React.createElement('div', { - key: 'create-flow', - className: "w-full max-w-3xl space-y-6" - }, [ - React.createElement('div', { - key: 'header', - className: "text-center" - }, [ - React.createElement('button', { - key: 'back', - onClick: resetToSelect, - className: "mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm" - }, [ - React.createElement('i', { - className: 'fas fa-arrow-left mr-2' - }), - 'Back to selection' - ]), - React.createElement('h2', { - key: 'title', - className: "text-xl font-semibold text-primary mb-2" - }, 'Creating a secure channel') - ]), - - // Step 1 - React.createElement('div', { - key: 'step1', - className: "card-minimal rounded-xl p-6" - }, [ - React.createElement('div', { - key: 'step-header', - className: "flex items-center mb-4" - }, [ - React.createElement('div', { - key: 'number', - className: "step-number mr-3" - }, '1'), - React.createElement('h3', { - key: 'title', - className: "text-lg font-medium text-primary" - }, "Generating ECDH keys and verification code") - ]), - React.createElement('p', { - key: 'description', - className: "text-secondary text-sm mb-4" - }, "Creating cryptographically strong keys and codes to protect against attacks"), - React.createElement('button', { - key: 'create-btn', - onClick: onCreateOffer, - disabled: connectionStatus === 'connecting' || showOfferStep, - className: `w-full btn-primary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed` - }, [ - React.createElement('i', { - className: 'fas fa-shield-alt mr-2' - }), - showOfferStep ? 'Keys created ✓' : 'Create secure keys' - ]), - - showOfferStep && React.createElement('div', { - key: 'offer-result', - className: "mt-6 space-y-4" - }, [ - React.createElement('div', { - key: 'success', - className: "p-3 bg-green-500/10 border border-green-500/20 rounded-lg" - }, [ - React.createElement('p', { - className: "text-green-400 text-sm font-medium flex items-center" - }, [ - React.createElement('i', { - className: 'fas fa-check-circle mr-2' - }), - 'Secure invitation created! Send the code to your contact:' - ]) - ]), - React.createElement('div', { - key: 'offer-data', - className: "space-y-3" - }, [ - React.createElement('textarea', { - key: 'textarea', - value: typeof offerData === 'object' ? JSON.stringify(offerData, null, 2) : offerData, - readOnly: true, - rows: 8, - className: "w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg font-mono text-xs text-secondary resize-none custom-scrollbar" - }), - React.createElement(EnhancedCopyButton, { - key: 'copy', - text: typeof offerData === 'object' ? JSON.stringify(offerData, null, 2) : offerData, - className: "w-full px-3 py-2 bg-orange-500/10 hover:bg-orange-500/20 text-orange-400 border border-orange-500/20 rounded text-sm font-medium" - }, 'Copy invitation code') - ]) - ]) - ]), - - // Step 2 - Session Type Selection - // showOfferStep && React.createElement('div', { - // key: 'step2', - // className: "card-minimal rounded-xl p-6" - // }, [ - // React.createElement('div', { - // key: 'step-header', - // className: "flex items-center mb-4" - // }, [ - // React.createElement('div', { - // key: 'number', - // className: "w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3" - // }, '2'), - // React.createElement('h3', { - // key: 'title', - // className: "text-lg font-medium text-primary" - // }, "Select session type") - // ]), - // React.createElement('p', { - // key: 'description', - // className: "text-secondary text-sm mb-4" - // }, "Choose a session plan or use limited demo mode for testing."), - // React.createElement(SessionTypeSelector, { - // key: 'session-selector', - // onSelectType: (sessionType) => { - // // Save the selected session type - // setSelectedSessionType(sessionType); - // console.log('🎯 Session type selected:', sessionType); - - // // FIX: For demo sessions, we immediately call automatic activation - // if (sessionType === 'demo') { - // console.log('🎮 Demo session selected, scheduling automatic activation...'); - // // Delay activation for 2 seconds to stabilize - // setTimeout(() => { - // if (sessionManager) { - // console.log('🚀 Triggering demo session activation from selection...'); - // handleDemoVerification(); - // } - // }, 2000); - // } - - // // Open a modal payment window - // if (typeof window.showPaymentModal === 'function') { - // window.showPaymentModal(sessionType); - // } else { - // // Fallback - show session information - // console.log('Selected session type:', sessionType); - // } - // }, - // onCancel: resetToSelect, - // sessionManager: window.sessionManager - // }) - // ]), - - // Step 3 - Waiting for response - showOfferStep && React.createElement('div', { - key: 'step2', - className: "card-minimal rounded-xl p-6" - }, [ - React.createElement('div', { - key: 'step-header', - className: "flex items-center mb-4" - }, [ - React.createElement('div', { - key: 'number', - className: "w-8 h-8 bg-blue-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3" - }, '2'), - React.createElement('h3', { - key: 'title', - className: "text-lg font-medium text-primary" - }, "Waiting for the peer's response") - ]), - React.createElement('p', { - key: 'description', - className: "text-secondary text-sm mb-4" - }, "Paste the encrypted invitation code from your contact."), - React.createElement('textarea', { - key: 'input', - value: answerInput, - onChange: (e) => setAnswerInput(e.target.value), - rows: 6, - placeholder: "Paste the encrypted response code from your contact...", - className: "w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-orange-500/40 focus:outline-none transition-all custom-scrollbar text-sm" - }), - React.createElement('button', { - key: 'connect-btn', - onClick: onConnect, - disabled: !answerInput.trim(), - className: "w-full btn-secondary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" - }, [ - React.createElement('i', { - className: 'fas fa-rocket mr-2' - }), - 'Establish connection' - ]) - ]) - ]) - ]); - } - - if (mode === 'join') { - return React.createElement('div', { - className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" - }, [ - React.createElement('div', { - key: 'join-flow', - className: "w-full max-w-3xl space-y-6" - }, [ - React.createElement('div', { - key: 'header', - className: "text-center" - }, [ - React.createElement('button', { - key: 'back', - onClick: resetToSelect, - className: "mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm" - }, [ - React.createElement('i', { - className: 'fas fa-arrow-left mr-2' - }), - 'Back to selection' - ]), - React.createElement('h2', { - key: 'title', - className: "text-xl font-semibold text-primary mb-2" - }, 'Joining the secure channel') - ]), - - // Step 1 - React.createElement('div', { - key: 'step1', - className: "card-minimal rounded-xl p-6" - }, [ - React.createElement('div', { - key: 'step-header', - className: "flex items-center mb-4" - }, [ - React.createElement('div', { - key: 'number', - className: "w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3" - }, '1'), - React.createElement('h3', { - key: 'title', - className: "text-lg font-medium text-primary" - }, "Paste secure invitation") - ]), - React.createElement('p', { - key: 'description', - className: "text-secondary text-sm mb-4" - }, "Copy and paste the encrypted invitation code from the initiator."), - React.createElement('textarea', { - key: 'input', - value: offerInput, - onChange: (e) => setOfferInput(e.target.value), - rows: 8, - placeholder: "Paste the encrypted invitation code...", - className: "w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm" - }), - React.createElement('button', { - key: 'process-btn', - onClick: onCreateAnswer, - disabled: !offerInput.trim() || connectionStatus === 'connecting', - className: "w-full btn-secondary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" - }, [ - React.createElement('i', { - className: 'fas fa-cogs mr-2' - }), - 'Process the invitation' - ]) - ]), - - // Step 2 - showAnswerStep && React.createElement('div', { - key: 'step2', - className: "card-minimal rounded-xl p-6" - }, [ - React.createElement('div', { - key: 'step-header', - className: "flex items-center mb-4" - }, [ - React.createElement('div', { - key: 'number', - className: "step-number mr-3" - }, '2'), - React.createElement('h3', { - key: 'title', - className: "text-lg font-medium text-primary" - }, "Sending a secure response") - ]), - React.createElement('div', { - key: 'success', - className: "p-3 bg-green-500/10 border border-green-500/20 rounded-lg mb-4" - }, [ - React.createElement('p', { - className: "text-green-400 text-sm font-medium flex items-center" - }, [ - React.createElement('i', { - className: 'fas fa-check-circle mr-2' - }), - 'Secure response created! Send this code to the initiator:' - ]) - ]), - React.createElement('div', { - key: 'answer-data', - className: "space-y-3 mb-4" - }, [ - React.createElement('textarea', { - key: 'textarea', - value: typeof answerData === 'object' ? JSON.stringify(answerData, null, 2) : answerData, - readOnly: true, - rows: 6, - className: "w-full p-3 bg-custom-bg border border-green-500/20 rounded-lg font-mono text-xs text-secondary resize-none custom-scrollbar" - }), - React.createElement(EnhancedCopyButton, { - key: 'copy', - text: typeof answerData === 'object' ? JSON.stringify(answerData, null, 2) : answerData, - className: "w-full px-3 py-2 bg-green-500/10 hover:bg-green-500/20 text-green-400 border border-green-500/20 rounded text-sm font-medium" - }, 'Copy response code') - ]), - React.createElement('div', { - key: 'info', - className: "p-3 bg-purple-500/10 border border-purple-500/20 rounded-lg" - }, [ - React.createElement('p', { - className: "text-purple-400 text-sm flex items-center justify-center" - }, [ - React.createElement('i', { - className: 'fas fa-shield-alt mr-2' - }), - 'The connection will be established with verification' - ]) - ]) - ]) - ]) - ]); - } - }; - - const EnhancedChatInterface = ({ - messages, - messageInput, - setMessageInput, - onSendMessage, - onDisconnect, - keyFingerprint, - isVerified, - chatMessagesRef, - scrollToBottom, - webrtcManager -}) => { - const [showScrollButton, setShowScrollButton] = React.useState(false); - const [showFileTransfer, setShowFileTransfer] = React.useState(false); - - // Автоматическая прокрутка при изменении сообщений - React.useEffect(() => { - if (chatMessagesRef.current && messages.length > 0) { - const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current; - const isNearBottom = scrollHeight - scrollTop - clientHeight < 100; - if (isNearBottom) { - const smoothScroll = () => { - if (chatMessagesRef.current) { - chatMessagesRef.current.scrollTo({ - top: chatMessagesRef.current.scrollHeight, - behavior: 'smooth' - }); - } - }; - smoothScroll(); - setTimeout(smoothScroll, 50); - setTimeout(smoothScroll, 150); - } - } - }, [messages, chatMessagesRef]); - - // Обработчик скролла - const handleScroll = () => { - if (chatMessagesRef.current) { - const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current; - const isNearBottom = scrollHeight - scrollTop - clientHeight < 100; - setShowScrollButton(!isNearBottom); - } - }; - - // Прокрутка вниз по кнопке - const handleScrollToBottom = () => { - scrollToBottom(); - setShowScrollButton(false); - }; - - // Обработчик нажатия Enter - const handleKeyPress = (e) => { - if (e.key === 'Enter' && !e.shiftKey) { - e.preventDefault(); - onSendMessage(); - } - }; - - // ИСПРАВЛЕНИЕ: Проверка готовности для файловых трансферов - const isFileTransferReady = () => { - if (!webrtcManager) return false; - - const connected = webrtcManager.isConnected ? webrtcManager.isConnected() : false; - const verified = webrtcManager.isVerified || false; - const hasDataChannel = webrtcManager.dataChannel && webrtcManager.dataChannel.readyState === 'open'; - - return connected && verified && hasDataChannel; - }; - - // Возврат JSX через React.createElement - return React.createElement( - 'div', - { - className: "chat-container flex flex-col", - style: { backgroundColor: '#272827', height: 'calc(100vh - 64px)' } - }, - [ - // Область сообщений - React.createElement( - 'div', - { className: "flex-1 flex flex-col overflow-hidden" }, - React.createElement( - 'div', - { className: "flex-1 max-w-4xl mx-auto w-full p-4 overflow-hidden" }, - React.createElement( - 'div', - { - ref: chatMessagesRef, - onScroll: handleScroll, - className: "h-full overflow-y-auto space-y-3 hide-scrollbar pr-2 scroll-smooth" - }, - messages.length === 0 ? - React.createElement( - 'div', - { className: "flex items-center justify-center h-full" }, - React.createElement( - 'div', - { className: "text-center max-w-md" }, - [ - React.createElement( - 'div', - { className: "w-16 h-16 bg-green-500/10 border border-green-500/20 rounded-xl flex items-center justify-center mx-auto mb-4" }, - React.createElement( - 'svg', - { className: "w-8 h-8 text-green-500", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, - React.createElement('path', { - strokeLinecap: "round", - strokeLinejoin: "round", - strokeWidth: 2, - d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" - }) - ) - ), - React.createElement('h3', { className: "text-lg font-medium text-gray-300 mb-2" }, "Secure channel is ready!"), - React.createElement('p', { className: "text-gray-400 text-sm mb-4" }, "All messages are protected by modern cryptographic algorithms"), - React.createElement( - 'div', - { className: "text-left space-y-2" }, - [ - ['End-to-end encryption', 'M5 13l4 4L19 7'], - ['Protection against replay attacks', 'M5 13l4 4L19 7'], - ['Integrity verification', 'M5 13l4 4L19 7'], - ['Perfect Forward Secrecy', 'M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15'] - ].map(([text, d], i) => - React.createElement( - 'div', - { key: `f${i}`, className: "flex items-center text-sm text-gray-400" }, - [ - React.createElement( - 'svg', - { - className: `w-4 h-4 mr-3 ${i === 3 ? 'text-purple-500' : 'text-green-500'}`, - fill: "none", - stroke: "currentColor", - viewBox: "0 0 24 24" - }, - React.createElement('path', { - strokeLinecap: "round", - strokeLinejoin: "round", - strokeWidth: 2, - d: d - }) - ), - text - ] - ) - ) - ) - ] - ) - ) : - messages.map((msg) => - React.createElement(EnhancedChatMessage, { - key: msg.id, - message: msg.message, - type: msg.type, - timestamp: msg.timestamp - }) - ) - ) - ) - ), - - // Кнопка прокрутки вниз - showScrollButton && - React.createElement( - 'button', - { - onClick: handleScrollToBottom, - className: "fixed right-6 w-12 h-12 bg-green-500/20 hover:bg-green-500/30 border border-green-500/30 text-green-400 rounded-full flex items-center justify-center transition-all duration-200 shadow-lg z-50", - style: { bottom: '160px' } - }, - React.createElement( - 'svg', - { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, - React.createElement('path', { - strokeLinecap: "round", - strokeLinejoin: "round", - strokeWidth: 2, - d: "M19 14l-7 7m0 0l-7-7m7 7V3" - }) - ) - ), - - // Секция передачи файлов - React.createElement( - 'div', - { - className: "flex-shrink-0 border-t border-gray-500/10", - style: { backgroundColor: '#272827' } - }, - React.createElement( - 'div', - { className: "max-w-4xl mx-auto px-4" }, - [ - React.createElement( - 'button', - { - onClick: () => setShowFileTransfer(!showFileTransfer), - className: `flex items-center text-sm text-gray-400 hover:text-gray-300 transition-colors py-4 ${showFileTransfer ? 'mb-4' : ''}` - }, - [ - React.createElement( - 'svg', - { - className: `w-4 h-4 mr-2 transform transition-transform ${showFileTransfer ? 'rotate-180' : ''}`, - fill: "none", - stroke: "currentColor", - viewBox: "0 0 24 24" - }, - showFileTransfer ? - React.createElement('path', { - strokeLinecap: "round", - strokeLinejoin: "round", - strokeWidth: 2, - d: "M5 15l7-7 7 7" - }) : - React.createElement('path', { - strokeLinecap: "round", - strokeLinejoin: "round", - strokeWidth: 2, - d: "M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13" - }) - ), - showFileTransfer ? 'Hide file transfer' : 'Send files' - ] - ), - // ИСПРАВЛЕНИЕ: Используем правильный компонент - showFileTransfer && - React.createElement(window.FileTransferComponent || (() => - React.createElement('div', { - className: "p-4 text-center text-red-400" - }, 'FileTransferComponent not loaded') - ), { - webrtcManager: webrtcManager, - isConnected: isFileTransferReady() - }) - ] - ) - ), - - // Область ввода сообщений - React.createElement( - 'div', - { className: "border-t border-gray-500/10" }, - React.createElement( - 'div', - { className: "max-w-4xl mx-auto p-4" }, - React.createElement( - 'div', - { className: "flex items-stretch space-x-3" }, - [ - React.createElement( - 'div', - { className: "flex-1 relative" }, - [ - React.createElement('textarea', { - value: messageInput, - onChange: (e) => setMessageInput(e.target.value), - onKeyDown: handleKeyPress, - placeholder: "Enter message to encrypt...", - rows: 2, - maxLength: 2000, - style: { backgroundColor: '#272827' }, - className: "w-full p-3 border border-gray-600 rounded-lg resize-none text-gray-300 placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm" - }), - React.createElement( - 'div', - { className: "absolute bottom-2 right-3 flex items-center space-x-2 text-xs text-gray-400" }, - [ - React.createElement('span', null, `${messageInput.length}/2000`), - React.createElement('span', null, "• Enter to send") - ] - ) - ] - ), - React.createElement( - 'button', - { - onClick: onSendMessage, - disabled: !messageInput.trim(), - className: "bg-green-400/20 text-green-400 p-3 rounded-lg transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center min-h-[72px]" - }, - React.createElement( - 'svg', - { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, - React.createElement('path', { - strokeLinecap: "round", - strokeLinejoin: "round", - strokeWidth: 2, - d: "M12 19l9 2-9-18-9 18 9-2zm0 0v-8" - }) - ) - ) - ] - ) - ) - ) - ] - ); -}; - - - // Main Enhanced Application Component - const EnhancedSecureP2PChat = () => { - const [messages, setMessages] = React.useState([]); - const [connectionStatus, setConnectionStatus] = React.useState('disconnected'); - - React.useEffect(() => { - if (messages.length > 0 && chatMessagesRef.current) { - const scrollToBottom = () => { - if (chatMessagesRef.current) { - chatMessagesRef.current.scrollTo({ - top: chatMessagesRef.current.scrollHeight, - behavior: 'smooth' - }); - } - }; - - scrollToBottom(); - setTimeout(scrollToBottom, 50); - setTimeout(scrollToBottom, 150); - } - }, [messages]); - const [messageInput, setMessageInput] = React.useState(''); - const [offerData, setOfferData] = React.useState(''); - const [answerData, setAnswerData] = React.useState(''); - const [offerInput, setOfferInput] = React.useState(''); - const [answerInput, setAnswerInput] = React.useState(''); - const [keyFingerprint, setKeyFingerprint] = React.useState(''); - const [verificationCode, setVerificationCode] = React.useState(''); - const [showOfferStep, setShowOfferStep] = React.useState(false); - const [showAnswerStep, setShowAnswerStep] = React.useState(false); - const [showVerification, setShowVerification] = React.useState(false); - const [isVerified, setIsVerified] = React.useState(false); - const [securityLevel, setSecurityLevel] = React.useState(null); - - // Mutual verification states - const [localVerificationConfirmed, setLocalVerificationConfirmed] = React.useState(false); - const [remoteVerificationConfirmed, setRemoteVerificationConfirmed] = React.useState(false); - const [bothVerificationsConfirmed, setBothVerificationsConfirmed] = React.useState(false); - - // PAKE password states removed - using SAS verification instead - - // Pay-per-session state - const [sessionManager, setSessionManager] = React.useState(null); - const [showPaymentModal, setShowPaymentModal] = React.useState(false); - const [sessionTimeLeft, setSessionTimeLeft] = React.useState(0); - const [pendingSession, setPendingSession] = React.useState(null); // { type, preimage } - const [selectedSessionType, setSelectedSessionType] = React.useState(null); // 'demo', 'basic', 'premium' - - // Initialize sessionManager after loading modules - React.useEffect(() => { - if (window.PayPerSessionManager && !sessionManager) { - console.log('💰 Initializing PayPerSessionManager...'); - const newSessionManager = new window.PayPerSessionManager(); - setSessionManager(newSessionManager); - window.sessionManager = newSessionManager; - console.log('✅ PayPerSessionManager initialized successfully'); - } - }, [sessionManager]); - - - - // Global functions for accessing modal windows - React.useEffect(() => { - if (!sessionManager) return; - - window.showPaymentModal = (sessionType) => { - setShowPaymentModal(true); - // Pass the selected session type to the modal window - if (sessionType) { - console.log('Opening payment modal for session type:', sessionType); - } - }; - window.sessionManager = sessionManager; - window.forceCleanup = () => { - handleClearData(); - if (webrtcManagerRef.current) { - webrtcManagerRef.current.disconnect(); - } - if (sessionManager) { - sessionManager.cleanup(); - } - }; - - window.forceSessionReset = () => { - if (sessionManager) { - sessionManager.resetSession(); - } - setSessionTimeLeft(0); - }; - - window.forceSessionCleanup = () => { - if (sessionManager) { - sessionManager.cleanup(); - } - setSessionTimeLeft(0); - setSessionManager(null); - }; - - window.clearLogs = () => { - if (typeof console.clear === 'function') { - console.clear(); - } - }; - - return () => { - delete window.showPaymentModal; - delete window.sessionManager; - delete window.forceCleanup; - delete window.forceSessionReset; - delete window.forceSessionCleanup; - delete window.clearLogs; - }; - }, [sessionManager]); - - const webrtcManagerRef = React.useRef(null); - // Expose for modules/UI that run outside this closure (e.g., inline handlers) - // Safe because it's a ref object and we maintain it centrally here - window.webrtcManagerRef = webrtcManagerRef; - - const addMessageWithAutoScroll = React.useCallback((message, type) => { - const newMessage = { - message, - type, - id: Date.now() + Math.random(), - timestamp: Date.now() - }; - - setMessages(prev => { - const updated = [...prev, newMessage]; - - setTimeout(() => { - if (chatMessagesRef?.current) { - const container = chatMessagesRef.current; - try { - const { scrollTop, scrollHeight, clientHeight } = container; - const isNearBottom = scrollHeight - scrollTop - clientHeight < 100; - - if (isNearBottom || prev.length === 0) { - requestAnimationFrame(() => { - if (container && container.scrollTo) { - container.scrollTo({ - top: container.scrollHeight, - behavior: 'smooth' - }); - } - }); - } - } catch (error) { - console.warn('Scroll error:', error); - container.scrollTop = container.scrollHeight; - } - } - }, 50); - - return updated; - }); - }, []); - - // Update security level based on real verification - const updateSecurityLevel = React.useCallback(async () => { - if (window.isUpdatingSecurity) { - return; - } - - window.isUpdatingSecurity = true; - - try { - if (webrtcManagerRef.current) { - const level = await webrtcManagerRef.current.calculateSecurityLevel(); - setSecurityLevel(level); - - if (window.DEBUG_MODE) { - console.log('🔒 Security level updated:', { - level: level.level, - score: level.score, - sessionType: level.sessionType, - passedChecks: level.passedChecks, - totalChecks: level.totalChecks - }); - } - } - } catch (error) { - console.error('Failed to update security level:', error); - setSecurityLevel({ - level: 'ERROR', - score: 0, - color: 'red', - details: 'Verification failed' - }); - } finally { - setTimeout(() => { - window.isUpdatingSecurity = false; - }, 2000); - } - }, []); - - // Session time ticker - React.useEffect(() => { - if (!sessionManager) return; - - const timer = setInterval(() => { - if (sessionManager.hasActiveSession()) { - setSessionTimeLeft(sessionManager.getTimeLeft()); - } else { - setSessionTimeLeft(0); - } - }, 1000); - return () => clearInterval(timer); - }, [sessionManager]); - - // Session expiration handler - React.useEffect(() => { - if (!sessionManager) return; - - sessionManager.onSessionExpired = () => { - setMessages(prev => [...prev, { - message: '⏰ Session time expired. The connection will be terminated.', - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - setTimeout(() => handleDisconnect(), 3000); - }; - }, [sessionManager]); - - // Automatic activation of demo session after successful verification - React.useEffect(() => { - if (!sessionManager) return; - - // Listen to demo session verification events - const handleDemoVerification = async () => { - try { - // Check if there is an active demo session - if (sessionManager.hasActiveSession()) { - console.log('✅ Demo session already active'); - return; - } - - // Diagnose sessionManager state - console.log('🔍 SessionManager state before activation:', { - hasActiveSession: sessionManager.hasActiveSession(), - timeLeft: sessionManager.getTimeLeft(), - currentSession: sessionManager.currentSession - }); - - window.pendingDemoActivation = true; - - setTimeout(async () => { - if (window.pendingDemoActivation && sessionManager) { - let result = null; - - const demoSession = sessionManager.createDemoSessionForActivation(); - - if (!demoSession.success) { - return; - } - - result = await sessionManager.safeActivateSession( - 'demo', - demoSession.preimage, - demoSession.paymentHash - ); - - if (result && result.success) { - setSessionTimeLeft(sessionManager.getTimeLeft()); - - setMessages(prev => [...prev, { - message: `🎮 Demo session activated for ${Math.round(result.timeLeft / 60000)} minutes`, - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - - window.pendingDemoActivation = false; - } else { - window.pendingDemoActivation = false; - } - } - }, 3000); - } catch (error) { - console.error('❌ Error activating demo session automatically:', error); - } - }; - - if (connectionStatus === 'connected' && isVerified) { - setTimeout(handleDemoVerification, 1000); - } - - if (selectedSessionType === 'demo' && connectionStatus === 'connected' && isVerified) { - setTimeout(handleDemoVerification, 1000); - } - - }, [sessionManager, connectionStatus, isVerified, selectedSessionType]); - const chatMessagesRef = React.useRef(null); - - // Scroll down function - const scrollToBottom = () => { - if (chatMessagesRef.current) { - const scrollAttempt = () => { - if (chatMessagesRef.current) { - chatMessagesRef.current.scrollTo({ - top: chatMessagesRef.current.scrollHeight, - behavior: 'smooth' - }); - } - }; - scrollAttempt(); - - setTimeout(scrollAttempt, 50); - setTimeout(scrollAttempt, 150); - setTimeout(scrollAttempt, 300); - - requestAnimationFrame(() => { - setTimeout(scrollAttempt, 100); - }); - } - }; - - // PAKE password functions removed - using SAS verification instead - - React.useEffect(() => { - // Prevent multiple initializations - if (webrtcManagerRef.current) { - console.log('⚠️ WebRTC Manager already initialized, skipping...'); - return; - } - - const handleMessage = (message, type) => { - // Дополнительная проверка на файловые и системные сообщения - if (typeof message === 'string' && message.trim().startsWith('{')) { - try { - const parsedMessage = JSON.parse(message); - const blockedTypes = [ - 'file_transfer_start', - 'file_transfer_response', - 'file_chunk', - 'chunk_confirmation', - 'file_transfer_complete', - 'file_transfer_error', - 'heartbeat', - 'verification', - 'verification_response', - 'verification_confirmed', - 'verification_both_confirmed', - 'peer_disconnect', - 'key_rotation_signal', - 'key_rotation_ready', - 'security_upgrade' - ]; - if (parsedMessage.type && blockedTypes.includes(parsedMessage.type)) { - console.log(`🛑 Blocked system/file message from chat: ${parsedMessage.type}`); - return; // Не показываем системные и файловые сообщения в чате - } - } catch (parseError) { - // Не JSON - это нормально для обычных текстовых сообщений - } - } - - addMessageWithAutoScroll(message, type); - }; - - const handleStatusChange = (status) => { - console.log('handleStatusChange called with status:', status); - setConnectionStatus(status); - - if (status === 'connected') { - document.dispatchEvent(new CustomEvent('new-connection')); - - // Не скрываем верификацию при 'connected' - только при 'verified' - // setIsVerified(true); - // setShowVerification(false); - if (!window.isUpdatingSecurity) { - updateSecurityLevel().catch(console.error); - } - } else if (status === 'verifying') { - console.log('Setting showVerification to true for verifying status'); - setShowVerification(true); - if (!window.isUpdatingSecurity) { - updateSecurityLevel().catch(console.error); - } - } else if (status === 'verified') { - setIsVerified(true); - setShowVerification(false); - setBothVerificationsConfirmed(true); - // CRITICAL: Set connectionStatus to 'connected' to show chat - setConnectionStatus('connected'); - if (!window.isUpdatingSecurity) { - updateSecurityLevel().catch(console.error); - } - } else if (status === 'connecting') { - if (!window.isUpdatingSecurity) { - updateSecurityLevel().catch(console.error); - } - } else if (status === 'disconnected') { - // При разрыве соединения очищаем все данные - setConnectionStatus('disconnected'); - setIsVerified(false); - setShowVerification(false); - - // Dispatch disconnected event for SessionTimer - document.dispatchEvent(new CustomEvent('disconnected')); - - // Clear verification states - setLocalVerificationConfirmed(false); - setRemoteVerificationConfirmed(false); - setBothVerificationsConfirmed(false); - - // Clear connection data - setOfferData(null); - setAnswerData(null); - setOfferInput(''); - setAnswerInput(''); - setShowOfferStep(false); - setShowAnswerStep(false); - setKeyFingerprint(''); - setVerificationCode(''); - setSecurityLevel(null); - - // Reset session and timer - if (sessionManager && sessionManager.hasActiveSession()) { - sessionManager.resetSession(); - setSessionTimeLeft(0); - setHasActiveSession(false); - } - - // Return to main page after a short delay - setTimeout(() => { - setConnectionStatus('disconnected'); - setShowVerification(false); - setOfferData(null); - setAnswerData(null); - setOfferInput(''); - setAnswerInput(''); - setShowOfferStep(false); - setShowAnswerStep(false); - setMessages([]); - }, 1000); - - // Не очищаем консоль при разрыве соединения - // чтобы пользователь мог видеть ошибки - } else if (status === 'peer_disconnected') { - if (sessionManager && sessionManager.hasActiveSession()) { - sessionManager.resetSession(); - setSessionTimeLeft(0); - setHasActiveSession(false); - } - - document.dispatchEvent(new CustomEvent('peer-disconnect')); - - // A short delay before clearing to display the status - setTimeout(() => { - setKeyFingerprint(''); - setVerificationCode(''); - setSecurityLevel(null); - setIsVerified(false); - setShowVerification(false); - setConnectionStatus('disconnected'); - - // Clear verification states - setLocalVerificationConfirmed(false); - setRemoteVerificationConfirmed(false); - setBothVerificationsConfirmed(false); - - // Clear connection data - setOfferData(null); - setAnswerData(null); - setOfferInput(''); - setAnswerInput(''); - setShowOfferStep(false); - setShowAnswerStep(false); - setMessages([]); - - // Не очищаем консоль при отключении пира - // чтобы сохранить историю соединения - // if (typeof console.clear === 'function') { - // console.clear(); - // } - - setSessionManager(null); - }, 2000); - } - }; - - const handleKeyExchange = (fingerprint) => { - console.log('handleKeyExchange called with fingerprint:', fingerprint); - if (fingerprint === '') { - setKeyFingerprint(''); - } else { - setKeyFingerprint(fingerprint); - console.log('Key fingerprint set in UI:', fingerprint); - } - }; - - const handleVerificationRequired = (code) => { - console.log('handleVerificationRequired called with code:', code); - if (code === '') { - setVerificationCode(''); - setShowVerification(false); - } else { - setVerificationCode(code); - setShowVerification(true); - console.log('Verification code set, showing verification UI'); - } - }; - - const handleVerificationStateChange = (state) => { - console.log('handleVerificationStateChange called with state:', state); - setLocalVerificationConfirmed(state.localConfirmed); - setRemoteVerificationConfirmed(state.remoteConfirmed); - setBothVerificationsConfirmed(state.bothConfirmed); - }; - - // Callback for handling response errors - const handleAnswerError = (errorType, errorMessage) => { - if (errorType === 'replay_attack') { - // Reset the session upon replay attack - if (sessionManager.hasActiveSession()) { - sessionManager.resetSession(); - setSessionTimeLeft(0); - } - setPendingSession(null); - - addMessageWithAutoScroll('💡 Data is outdated. Please create a new invitation or use a current response code.', 'system'); - - if (typeof console.clear === 'function') { - console.clear(); - } - } else if (errorType === 'security_violation') { - // Reset the session upon security breach - if (sessionManager.hasActiveSession()) { - sessionManager.resetSession(); - setSessionTimeLeft(0); - } - setPendingSession(null); - - addMessageWithAutoScroll(`🔒 Security breach: ${errorMessage}`, 'system'); - - if (typeof console.clear === 'function') { - console.clear(); - } - } - }; - - // Create WebRTC Manager only once - console.log('🔧 Initializing WebRTC Manager...'); - - if (typeof console.clear === 'function') { - console.clear(); - } - - webrtcManagerRef.current = new EnhancedSecureWebRTCManager( - handleMessage, - handleStatusChange, - handleKeyExchange, - handleVerificationRequired, - handleAnswerError, - handleVerificationStateChange - ); - - handleMessage('🚀 SecureBit.chat Enhanced Security Edition v4.02.985 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.', 'system'); - - const handleBeforeUnload = (event) => { - if (event.type === 'beforeunload' && !isTabSwitching) { - console.log('🔌 Page unloading (closing tab) - sending disconnect notification'); - - if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) { - try { - webrtcManagerRef.current.sendSystemMessage({ - type: 'peer_disconnect', - reason: 'user_disconnect', - timestamp: Date.now() - }); - } catch (error) { - console.log('Could not send disconnect notification:', error.message); - } - - setTimeout(() => { - if (webrtcManagerRef.current) { - webrtcManagerRef.current.disconnect(); - } - }, 100); - } else if (webrtcManagerRef.current) { - webrtcManagerRef.current.disconnect(); - } - } else if (isTabSwitching) { - console.log('📱 Tab switching detected - NOT disconnecting'); - event.preventDefault(); - event.returnValue = ''; - } - }; - - window.addEventListener('beforeunload', handleBeforeUnload); - - let isTabSwitching = false; - let tabSwitchTimeout = null; - - const handleVisibilityChange = () => { - if (document.visibilityState === 'hidden') { - console.log('📱 Page hidden (tab switch) - keeping connection alive'); - isTabSwitching = true; - - if (tabSwitchTimeout) { - clearTimeout(tabSwitchTimeout); - } - - tabSwitchTimeout = setTimeout(() => { - isTabSwitching = false; - }, 5000); - - } else if (document.visibilityState === 'visible') { - console.log('📱 Page visible (tab restored) - connection maintained'); - isTabSwitching = false; - - if (tabSwitchTimeout) { - clearTimeout(tabSwitchTimeout); - tabSwitchTimeout = null; - } - } - }; - - document.addEventListener('visibilitychange', handleVisibilityChange); - - // Setup file transfer callbacks - if (webrtcManagerRef.current) { - webrtcManagerRef.current.setFileTransferCallbacks( - // Progress callback - (progress) => { - console.log('File progress:', progress); - }, - - // File received callback - (fileData) => { - const sizeMb = Math.max(1, Math.round((fileData.fileSize || 0) / (1024 * 1024))); - const downloadMessage = React.createElement('div', { - className: 'flex items-center space-x-2' - }, [ - React.createElement('span', { key: 'label' }, `📥 File received: ${fileData.fileName} (${sizeMb} MB)`), - React.createElement('button', { - key: 'btn', - className: 'px-3 py-1 rounded bg-blue-600 hover:bg-blue-700 text-white text-xs', - onClick: async () => { - try { - const url = await fileData.getObjectURL(); - const a = document.createElement('a'); - a.href = url; - a.download = fileData.fileName; - a.click(); - // Даем браузеру время начать загрузку, затем освобождаем URL - setTimeout(() => fileData.revokeObjectURL(url), 15000); - } catch (e) { - console.error('Download failed:', e); - addMessageWithAutoScroll(`❌ File upload error: ${String(e?.message || e)}`, 'system'); - } - } - }, 'Download') - ]); - - addMessageWithAutoScroll(downloadMessage, 'system'); - }, - - // Error callback - (error) => { - console.error('File transfer error:', error); - - if (error.includes('Connection not ready')) { - addMessageWithAutoScroll(`⚠️ File transfer error: connection not ready. Try again later.`, 'system'); - } else if (error.includes('File too large')) { - addMessageWithAutoScroll(`⚠️ File is too big. Maximum size: 100 MB`, 'system'); - } else { - addMessageWithAutoScroll(`❌ File transfer error: ${error}`, 'system'); - } - } - ); - } - - return () => { - window.removeEventListener('beforeunload', handleBeforeUnload); - document.removeEventListener('visibilitychange', handleVisibilityChange); - - if (tabSwitchTimeout) { - clearTimeout(tabSwitchTimeout); - tabSwitchTimeout = null; - } - - if (webrtcManagerRef.current) { - console.log('🧹 Cleaning up WebRTC Manager...'); - webrtcManagerRef.current.disconnect(); - webrtcManagerRef.current = null; - } - }; - }, []); // Empty dependency array to run only once - - const ensureActiveSessionOrPurchase = async () => { - if (sessionManager.hasActiveSession()) return true; - if (pendingSession) return true; - setShowPaymentModal(true); - return false; - }; - - const handleCreateOffer = async () => { - try { - console.log('🎯 handleCreateOffer called'); - const ok = await ensureActiveSessionOrPurchase(); - if (!ok) return; - - setOfferData(''); - setShowOfferStep(false); - - console.log('🎯 Calling createSecureOffer...'); - const offer = await webrtcManagerRef.current.createSecureOffer(); - console.log('🎯 createSecureOffer returned:', offer ? 'success' : 'null'); - - // Store offer data directly (no encryption needed with SAS) - setOfferData(offer); - setShowOfferStep(true); - - const existingMessages = messages.filter(m => - m.type === 'system' && - (m.message.includes('Secure invitation created') || m.message.includes('Send the encrypted code')) - ); - - if (existingMessages.length === 0) { - setMessages(prev => [...prev, { - message: '🔐 Secure invitation created and encrypted!', - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - - setMessages(prev => [...prev, { - message: '📤 Send the invitation code to your interlocutor via a secure channel (voice call, SMS, etc.)..', - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - - } - - if (!window.isUpdatingSecurity) { - updateSecurityLevel().catch(console.error); - } - } catch (error) { - setMessages(prev => [...prev, { - message: `❌ Error creating invitation: ${error.message}`, - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - } - }; - - const handleCreateAnswer = async () => { - try { - if (!offerInput.trim()) { - setMessages(prev => [...prev, { - message: '⚠️ You need to insert the invitation code from your interlocutor.', - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - return; - } - - try { - setMessages(prev => [...prev, { - message: '🔄 Processing the secure invitation...', - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - - setAnswerData(''); - setShowAnswerStep(false); - - let offer; - try { - // Parse the offer data directly (no decryption needed with SAS) - offer = JSON.parse(offerInput.trim()); - } catch (parseError) { - throw new Error(`Invalid invitation format: ${parseError.message}`); - } - - if (!offer || typeof offer !== 'object') { - throw new Error('The invitation must be an object'); - } - - if (!offer.type || offer.type !== 'enhanced_secure_offer') { - throw new Error('Invalid invitation type. Expected enhanced_secure_offer'); - } - - console.log('Creating secure answer for offer:', offer); - const answer = await webrtcManagerRef.current.createSecureAnswer(offer); - console.log('Secure answer created:', answer); - - // Store answer data directly (no encryption needed with SAS) - setAnswerData(answer); - setShowAnswerStep(true); - - const existingResponseMessages = messages.filter(m => - m.type === 'system' && - (m.message.includes('Secure response created') || m.message.includes('Send the response')) - ); - - if (existingResponseMessages.length === 0) { - setMessages(prev => [...prev, { - message: '✅ Secure response created!', - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - - setMessages(prev => [...prev, { - message: '📤 Send the response code to the initiator via a secure channel..', - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - - } - - // Update security level after creating answer - if (!window.isUpdatingSecurity) { - updateSecurityLevel().catch(console.error); - } - } catch (error) { - console.error('Error in handleCreateAnswer:', error); - setMessages(prev => [...prev, { - message: `❌ Error processing the invitation: ${error.message}`, - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - } - } catch (error) { - console.error('Error in handleCreateAnswer:', error); - setMessages(prev => [...prev, { - message: `❌ Invitation processing error: ${error.message}`, - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - } - }; - - const handleConnect = async () => { - try { - if (!answerInput.trim()) { - setMessages(prev => [...prev, { - message: '⚠️ You need to insert the response code from your interlocutor.', - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - return; - } - - try { - setMessages(prev => [...prev, { - message: '🔄 Processing the secure response...', - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - - let answer; - try { - // Parse the answer data directly (no decryption needed with SAS) - answer = JSON.parse(answerInput.trim()); - } catch (parseError) { - throw new Error(`Invalid response format: ${parseError.message}`); - } - - if (!answer || typeof answer !== 'object') { - throw new Error('The response must be an object'); - } - - if (!answer.type || answer.type !== 'enhanced_secure_answer') { - throw new Error('Invalid response type. Expected enhanced\_secure\_answer'); - } - - await webrtcManagerRef.current.handleSecureAnswer(answer); - - if (sessionManager.canActivateSession() && pendingSession) { - const result = sessionManager.safeActivateSession(pendingSession.type, pendingSession.preimage, pendingSession.paymentHash); - if (result.success) { - setPendingSession(null); - setSessionTimeLeft(sessionManager.getTimeLeft()); - setMessages(prev => [...prev, { - message: `💰 Session activated on ${sessionManager.sessionPrices[pendingSession.type].hours}ч (${result.method})`, - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - } else { - setMessages(prev => [...prev, { - message: `❌ Session activation error: ${result.reason}`, - type: 'error', - id: Date.now(), - timestamp: Date.now() - }]); - } - } - - setMessages(prev => [...prev, { - message: '🔄 Finalizing the secure connection...', - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - - // Update security level after handling answer - if (!window.isUpdatingSecurity) { - updateSecurityLevel().catch(console.error); - } - } catch (error) { - setMessages(prev => [...prev, { - message: `❌ Connection setup error: ${error.message}`, - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - - if (!error.message.includes('Too old') && !error.message.includes('too old')) { - setPendingSession(null); - } - } - } catch (error) { - setMessages(prev => [...prev, { - message: `❌ Connection setup error: ${error.message}`, - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - - if (!error.message.includes('сToo old') && !error.message.includes('too old')) { - setPendingSession(null); - } - } - }; - - const handleVerifyConnection = (isValid) => { - if (isValid) { - webrtcManagerRef.current.confirmVerification(); - // Mark local verification as confirmed - setLocalVerificationConfirmed(true); - } else { - setMessages(prev => [...prev, { - message: '❌ Verification rejected. The connection is unsafe! Session reset..', - type: 'system', - id: Date.now(), - timestamp: Date.now() - }]); - - // Clear verification states - setLocalVerificationConfirmed(false); - setRemoteVerificationConfirmed(false); - setBothVerificationsConfirmed(false); - setShowVerification(false); - setVerificationCode(''); - - // Reset UI to initial state - setConnectionStatus('disconnected'); - setOfferData(null); - setAnswerData(null); - setOfferInput(''); - setAnswerInput(''); - setShowOfferStep(false); - setShowAnswerStep(false); - setKeyFingerprint(''); - setSecurityLevel(null); - setIsVerified(false); - setMessages([]); - - sessionManager.resetSession(); - setSessionTimeLeft(0); - setPendingSession(null); - - // Dispatch disconnected event for SessionTimer - document.dispatchEvent(new CustomEvent('disconnected')); - - handleDisconnect(); - } - }; - - const handleSendMessage = async () => { - if (!messageInput.trim()) { - return; - } - - if (!webrtcManagerRef.current) { - return; - } - - if (!webrtcManagerRef.current.isConnected()) { - return; - } - - try { - - // Add the message to local messages immediately (sent message) - addMessageWithAutoScroll(messageInput.trim(), 'sent'); - - // Use sendMessage for simple text messages instead of sendSecureMessage - await webrtcManagerRef.current.sendMessage(messageInput); - setMessageInput(''); - } catch (error) { - const msg = String(error?.message || error); - if (!/queued for sending|Data channel not ready/i.test(msg)) { - addMessageWithAutoScroll(`❌ Sending error: ${msg}`,'system'); - } - } - }; - - const handleClearData = () => { - // Очищаем все состояния соединения - setOfferData(''); - setAnswerData(''); - setOfferInput(''); - setAnswerInput(''); - setShowOfferStep(false); - setShowAnswerStep(false); - setShowVerification(false); - setVerificationCode(''); - setIsVerified(false); - setKeyFingerprint(''); - setSecurityLevel(null); - setConnectionStatus('disconnected'); - setMessages([]); - setMessageInput(''); - - // Clear verification states - setLocalVerificationConfirmed(false); - setRemoteVerificationConfirmed(false); - setBothVerificationsConfirmed(false); - - // PAKE passwords removed - using SAS verification instead - - // Не очищаем консоль при очистке данных - // чтобы пользователь мог видеть ошибки - // if (typeof console.clear === 'function') { - // console.clear(); - // } - - // Cleanup pay-per-session state - if (sessionManager) { - sessionManager.cleanup(); - setSessionTimeLeft(0); - } - setShowPaymentModal(false); - - setPendingSession(null); - document.dispatchEvent(new CustomEvent('peer-disconnect')); - setSessionManager(null); - }; - - const handleDisconnect = () => { - if (sessionManager && sessionManager.hasActiveSession()) { - sessionManager.resetSession(); - setSessionTimeLeft(0); - } - - // Cleanup pay-per-session state - if (sessionManager) { - sessionManager.cleanup(); - } - setShowPaymentModal(false); - - if (webrtcManagerRef.current) { - webrtcManagerRef.current.disconnect(); - } - - setKeyFingerprint(''); - setVerificationCode(''); - setSecurityLevel(null); - setIsVerified(false); - setShowVerification(false); - setConnectionStatus('disconnected'); - - // Clear verification states - setLocalVerificationConfirmed(false); - setRemoteVerificationConfirmed(false); - setBothVerificationsConfirmed(false); - - // Reset UI to initial state - setConnectionStatus('disconnected'); - setShowVerification(false); - setOfferData(null); - setAnswerData(null); - setOfferInput(''); - setAnswerInput(''); - setShowOfferStep(false); - setShowAnswerStep(false); - setKeyFingerprint(''); - setVerificationCode(''); - setSecurityLevel(null); - setIsVerified(false); - - setMessages([]); - - // Не очищаем консоль при отключении - // чтобы пользователь мог видеть ошибки - // if (typeof console.clear === 'function') { - // console.clear(); - // } - - document.dispatchEvent(new CustomEvent('peer-disconnect')); - document.dispatchEvent(new CustomEvent('disconnected')); - - document.dispatchEvent(new CustomEvent('session-cleanup', { - detail: { - timestamp: Date.now(), - reason: 'manual_disconnect' - } - })); - - setTimeout(() => { - if (sessionManager && sessionManager.hasActiveSession()) { - sessionManager.resetSession(); - setSessionTimeLeft(0); - } - }, 500); - - handleClearData(); - - setTimeout(() => { - setSessionManager(null); - }, 1000); - }; - - const handleSessionActivated = (session) => { - let message; - if (session.type === 'demo') { - message = `🎮 Demo session activated for 6 minutes. You can create invitations!`; - } else { - const hours = sessionManager.sessionPrices[session.type]?.hours || 0; - message = `💰 Session activated for ${hours}h. You can create invitations!`; - } - - addMessageWithAutoScroll(message, 'system'); - - }; - - React.useEffect(() => { - if (connectionStatus === 'connected' && isVerified) { - addMessageWithAutoScroll('🎉 Secure connection successfully established and verified! You can now communicate safely with full protection against MITM attacks and Perfect Forward Secrecy..', 'system'); - - } - }, [connectionStatus, isVerified]); - - const isConnectedAndVerified = connectionStatus === 'connected' && isVerified; - - React.useEffect(() => { - if (isConnectedAndVerified && sessionManager.canActivateSession() && pendingSession && connectionStatus !== 'failed') { - const result = sessionManager.safeActivateSession(pendingSession.type, pendingSession.preimage, pendingSession.paymentHash); - if (result.success) { - setPendingSession(null); - setSessionTimeLeft(sessionManager.getTimeLeft()); - let message; - if (pendingSession.type === 'demo') { - message = `🎮 Demo session activated for 6 minutes (${result.method})`; - } else { - const hours = sessionManager.sessionPrices[pendingSession.type]?.hours || 0; - message = `💰 Session activated for ${hours}h (${result.method})`; - } - - addMessageWithAutoScroll(message, 'system'); - } else { - addMessageWithAutoScroll(`❌ Session activation error: ${result.reason}`, 'error'); - } - } - }, [isConnectedAndVerified, sessionManager, pendingSession, connectionStatus]); - - return React.createElement('div', { - className: "minimal-bg min-h-screen" - }, [ - React.createElement(EnhancedMinimalHeader, { - key: 'header', - status: connectionStatus, - fingerprint: keyFingerprint, - verificationCode: verificationCode, - onDisconnect: handleDisconnect, - isConnected: isConnectedAndVerified, - securityLevel: securityLevel, - sessionManager: sessionManager, - sessionTimeLeft: sessionTimeLeft - }), - - React.createElement('main', { - key: 'main' - }, - isConnectedAndVerified - ? React.createElement(EnhancedChatInterface, { - messages: messages, - messageInput: messageInput, - setMessageInput: setMessageInput, - onSendMessage: handleSendMessage, - onDisconnect: handleDisconnect, - keyFingerprint: keyFingerprint, - isVerified: isVerified, - chatMessagesRef: chatMessagesRef, - webrtcManager: webrtcManagerRef.current - }) - : React.createElement(EnhancedConnectionSetup, { - onCreateOffer: handleCreateOffer, - onCreateAnswer: handleCreateAnswer, - onConnect: handleConnect, - onClearData: handleClearData, - onVerifyConnection: handleVerifyConnection, - connectionStatus: connectionStatus, - offerData: offerData, - answerData: answerData, - offerInput: offerInput, - setOfferInput: setOfferInput, - answerInput: answerInput, - setAnswerInput: setAnswerInput, - showOfferStep: showOfferStep, - showAnswerStep: showAnswerStep, - verificationCode: verificationCode, - showVerification: showVerification, - messages: messages, - localVerificationConfirmed: localVerificationConfirmed, - remoteVerificationConfirmed: remoteVerificationConfirmed, - bothVerificationsConfirmed: bothVerificationsConfirmed, - // PAKE passwords removed - using SAS verification instead - }) - ), - - // PAKE Password Modal removed - using SAS verification instead - - // Payment Modal - React.createElement(PaymentModal, { - key: 'payment-modal', - isOpen: showPaymentModal, - onClose: () => setShowPaymentModal(false), - sessionManager: sessionManager, - onSessionPurchased: (session) => { setPendingSession(session); handleSessionActivated({ type: session.type }); } - }) - ]); - }; - function initializeApp() { - if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureWebRTCManager) { - ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root')); - } else { - console.error('❌ Модули не загружены:', { - hasCrypto: !!window.EnhancedSecureCryptoUtils, - hasWebRTC: !!window.EnhancedSecureWebRTCManager - }); - } - } - // Render Enhanced Application - // ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root')); - - - - - - - + + + - \ No newline at end of file diff --git a/libs/babel/babel.min.js b/libs/babel/babel.min.js new file mode 100644 index 0000000..67ee5bc --- /dev/null +++ b/libs/babel/babel.min.js @@ -0,0 +1,4 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Babel={})}(this,function(e){"use strict";var t=Object.freeze({__proto__:null,get _call(){return yN},get _getQueueContexts(){return ON},get _resyncKey(){return TN},get _resyncList(){return PN},get _resyncParent(){return SN},get _resyncRemoved(){return AN},get call(){return gN},get isDenylisted(){return mN},get popContext(){return kN},get pushContext(){return CN},get requeue(){return DN},get requeueComputedKeyAndDecorators(){return NN},get resync(){return EN},get setContext(){return wN},get setKey(){return IN},get setScope(){return jN},get setup(){return _N},get skip(){return xN},get skipKey(){return vN},get stop(){return RN},get visit(){return bN}}),r=Object.freeze({__proto__:null,get DEFAULT_EXTENSIONS(){return WV},get File(){return fM},get buildExternalHelpers(){return LM},get createConfigItem(){return FW},get createConfigItemAsync(){return BW},get createConfigItemSync(){return MW},get getEnv(){return ZM},get loadOptions(){return NW},get loadOptionsAsync(){return IW},get loadOptionsSync(){return DW},get loadPartialConfig(){return kW},get loadPartialConfigAsync(){return PW},get loadPartialConfigSync(){return AW},get parse(){return MV},get parseAsync(){return LV},get parseSync(){return FV},get resolvePlugin(){return qV},get resolvePreset(){return GV},get template(){return fj},get tokTypes(){return sR},get transform(){return TV},get transformAsync(){return AV},get transformFile(){return kV},get transformFileAsync(){return _V},get transformFileSync(){return CV},get transformFromAst(){return DV},get transformFromAstAsync(){return OV},get transformFromAstSync(){return NV},get transformSync(){return PV},get traverse(){return UN},get types(){return $m},get version(){return UV}});function a(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,a=Array(t);r=e.length?{done:!0}:{done:!1,value:e[a++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function d(e){return d=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},d(e)}function c(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&y(e,t)}function l(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(l=function(){return!!e})()}function u(e,t){if(null==e)return{};var r={};for(var a in e)if({}.hasOwnProperty.call(e,a)){if(-1!==t.indexOf(a))continue;r[a]=e[a]}return r}function p(){ +/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ +var e,t,r="function"==typeof Symbol?Symbol:{},a=r.iterator||"@@iterator",n=r.toStringTag||"@@toStringTag";function s(r,a,n,s){var d=a&&a.prototype instanceof i?a:i,c=Object.create(d.prototype);return f(c,"_invoke",function(r,a,n){var s,i,d,c=0,l=n||[],u=!1,p={p:0,n:0,v:e,a:f,f:f.bind(e,4),d:function(t,r){return s=t,i=0,d=e,p.n=r,o}};function f(r,a){for(i=r,d=a,t=0;!u&&c&&!n&&t3?(n=g===a)&&(i=s[4]||3,d=s[5]===e?s[3]:s[5],s[4]=3,s[5]=e):s[0]<=f&&((n=r<2&&fa||a>g)&&(s[4]=r,s[5]=a,p.n=g,i=0))}if(n||r>1)return o;throw u=!0,a}return function(n,l,g){if(c>1)throw TypeError("Generator is already running");for(u&&1===l&&f(l,g),i=l,d=g;(t=i<2?e:d)||!u;){s||(i?i<3?(i>1&&(p.n=-1),f(i,d)):p.n=d:p.v=d);try{if(c=2,s){if(i||(n="next"),t=s[n]){if(!(t=t.call(s,d)))throw TypeError("iterator result is not an object");if(!t.done)return t;d=t.value,i<2&&(i=0)}else 1===i&&(t=s.return)&&t.call(s),i<2&&(d=TypeError("The iterator does not provide a '"+n+"' method"),i=1);s=e}else if((t=(u=p.n<0)?d:r.call(a,p))!==o)break}catch(t){s=e,i=1,d=t}finally{c=1}}return{value:t,done:u}}}(r,n,s),!0),c}var o={};function i(){}function d(){}function c(){}t=Object.getPrototypeOf;var l=[][a]?t(t([][a]())):(f(t={},a,function(){return this}),t),u=c.prototype=i.prototype=Object.create(l);function g(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,c):(e.__proto__=c,f(e,n,"GeneratorFunction")),e.prototype=Object.create(u),e}return d.prototype=c,f(u,"constructor",c),f(c,"constructor",d),d.displayName="GeneratorFunction",f(c,n,"GeneratorFunction"),f(u),f(u,n,"Generator"),f(u,a,function(){return this}),f(u,"toString",function(){return"[object Generator]"}),(p=function(){return{w:s,m:g}})()}function f(e,t,r,a){var n=Object.defineProperty;try{n({},"",{})}catch(e){n=0}f=function(e,t,r,a){if(t)n?n(e,t,{value:r,enumerable:!a,configurable:!a,writable:!a}):e[t]=r;else{function s(t,r){f(e,t,function(e){return this._invoke(t,r,e)})}s("next",0),s("throw",1),s("return",2)}},f(e,t,r,a)}function g(e){if(null!=e){var t=e["function"==typeof Symbol&&Symbol.iterator||"@@iterator"],r=0;if(t)return t.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length))return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}}}throw new TypeError(typeof e+" is not iterable")}function y(e,t){return y=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},y(e,t)}function m(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var a,n,s,o,i=[],d=!0,c=!1;try{if(s=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;d=!1}else for(;!(d=(a=s.call(r)).done)&&(i.push(a.value),i.length!==t);d=!0);}catch(e){c=!0,n=e}finally{try{if(!d&&null!=r.return&&(o=r.return(),Object(o)!==o))return}finally{if(c)throw n}}return i}}(e,t)||v(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function h(e,t){return t||(t=e.slice(0)),e.raw=t,e}function b(e){return function(e){if(Array.isArray(e))return a(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||v(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function x(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var a=r.call(e,t);if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e,"string");return"symbol"==typeof t?t:t+""}function v(e,t){if(e){if("string"==typeof e)return a(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?a(e,t):void 0}}function R(e){var t="function"==typeof Map?new Map:void 0;return R=function(e){if(null===e||!function(e){try{return-1!==Function.toString.call(e).indexOf("[native code]")}catch(t){return"function"==typeof e}}(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return function(e,t,r){if(l())return Reflect.construct.apply(null,arguments);var a=[null];a.push.apply(a,t);var n=new(e.bind.apply(e,a));return r&&y(n,r.prototype),n}(e,arguments,d(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),y(r,e)},R(e)}var j="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{};function w(){throw new Error("setTimeout has not been defined")}function E(){throw new Error("clearTimeout has not been defined")}var S=w,T=E;function P(e){if(S===setTimeout)return setTimeout(e,0);if((S===w||!S)&&setTimeout)return S=setTimeout,setTimeout(e,0);try{return S(e,0)}catch(t){try{return S.call(null,e,0)}catch(t){return S.call(this,e,0)}}}"function"==typeof j.setTimeout&&(S=setTimeout),"function"==typeof j.clearTimeout&&(T=clearTimeout);var A,k=[],C=!1,_=-1;function I(){C&&A&&(C=!1,A.length?k=A.concat(k):_=-1,k.length&&D())}function D(){if(!C){var e=P(I);C=!0;for(var t=k.length;t;){for(A=k,k=[];++_1)for(var r=1;rn.length)return!1;for(var i=0,d=s.length-1;ie)return!1;if((r+=t[a+1])>=e)return!0}return!1}function Ur(e){return e<65?36===e:e<=90||(e<97?95===e:e<=122||(e<=65535?e>=170&&Or.test(String.fromCharCode(e)):Lr(e,Mr)))}function qr(e){return e<48?36===e:e<58||!(e<65)&&(e<=90||(e<97?95===e:e<=122||(e<=65535?e>=170&&Br.test(String.fromCharCode(e)):Lr(e,Mr)||Lr(e,Fr))))}function Gr(e){for(var t=!0,r=0;r=48&&e<=57},ta={decBinOct:new Set([46,66,69,79,95,98,101,111]),hex:new Set([46,88,95,120])},ra={bin:function(e){return 48===e||49===e},oct:function(e){return e>=48&&e<=55},dec:function(e){return e>=48&&e<=57},hex:function(e){return e>=48&&e<=57||e>=65&&e<=70||e>=97&&e<=102}};function aa(e,t,r,a,n,s){for(var o=r,i=a,d=n,c="",l=null,u=r,p=t.length;;){if(r>=p){s.unterminated(o,i,d),c+=t.slice(u,r);break}var f=t.charCodeAt(r);if(na(e,f,t,r)){c+=t.slice(u,r);break}if(92===f){c+=t.slice(u,r);var g=sa(t,r,a,n,"template"===e,s);null!==g.ch||l?c+=g.ch:l={pos:r,lineStart:a,curLine:n},r=g.pos,a=g.lineStart,n=g.curLine,u=r}else 8232===f||8233===f?(++n,a=++r):10===f||13===f?"template"===e?(c+=t.slice(u,r)+"\n",++r,13===f&&10===t.charCodeAt(r)&&++r,++n,u=a=r):s.unterminated(o,i,d):++r}return{pos:r,str:c,firstInvalidLoc:l,lineStart:a,curLine:n,containsInvalid:!!l}}function na(e,t,r,a){return"template"===e?96===t||36===t&&123===r.charCodeAt(a+1):t===("double"===e?34:39)}function sa(e,t,r,a,n,s){var o=!n;t++;var i=function(e){return{pos:t,ch:e,lineStart:r,curLine:a}},d=e.charCodeAt(t++);switch(d){case 110:return i("\n");case 114:return i("\r");case 120:var c,l=oa(e,t,r,a,2,!1,o,s);return c=l.code,t=l.pos,i(null===c?null:String.fromCharCode(c));case 117:var u,p=da(e,t,r,a,o,s);return u=p.code,t=p.pos,i(null===u?null:String.fromCodePoint(u));case 116:return i("\t");case 98:return i("\b");case 118:return i("\v");case 102:return i("\f");case 13:10===e.charCodeAt(t)&&++t;case 10:r=t,++a;case 8232:case 8233:return i("");case 56:case 57:if(n)return i(null);s.strictNumericEscape(t-1,r,a);default:if(d>=48&&d<=55){var f=t-1,g=/^[0-7]+/.exec(e.slice(f,t+2))[0],y=parseInt(g,8);y>255&&(g=g.slice(0,-1),y=parseInt(g,8)),t+=g.length-1;var m=e.charCodeAt(t);if("0"!==g||56===m||57===m){if(n)return i(null);s.strictNumericEscape(f,r,a)}return i(String.fromCharCode(y))}return i(String.fromCharCode(d))}}function oa(e,t,r,a,n,s,o,i){var d,c=t,l=ia(e,t,r,a,16,n,s,!1,i,!o);return d=l.n,t=l.pos,null===d&&(o?i.invalidEscapeSequence(c,r,a):t=c-1),{code:d,pos:t}}function ia(e,t,r,a,n,s,o,i,d,c){for(var l=t,u=16===n?ta.hex:ta.decBinOct,p=16===n?ra.hex:10===n?ra.dec:8===n?ra.oct:ra.bin,f=!1,g=0,y=0,m=null==s?1/0:s;y=97?h-97+10:h>=65?h-65+10:ea(h)?h-48:1/0)>=n){if(b<=9&&c)return{n:null,pos:t};if(b<=9&&d.invalidDigit(t,r,a,n))b=0;else{if(!o)break;b=0,f=!0}}++t,g=g*n+b}else{var x=e.charCodeAt(t-1),v=e.charCodeAt(t+1);if(i){if(Number.isNaN(v)||!p(v)||u.has(x)||u.has(v)){if(c)return{n:null,pos:t};d.unexpectedNumericSeparator(t,r,a)}}else{if(c)return{n:null,pos:t};d.numericSeparatorInEscapeSequence(t,r,a)}++t}}return t===l||null!=s&&t-l!==s||f?{n:null,pos:t}:{n:g,pos:t}}function da(e,t,r,a,n,s){var o;if(123===e.charCodeAt(t)){var i=oa(e,++t,r,a,e.indexOf("}",t)-t,!0,n,s);if(o=i.code,t=i.pos,++t,null!==o&&o>1114111){if(!n)return{code:null,pos:t};s.invalidCodePoint(t,r,a)}}else{var d=oa(e,t,r,a,4,!1,n,s);o=d.code,t=d.pos}return{code:o,pos:t}}var ca=["consequent","body","alternate"],la=["leadingComments","trailingComments","innerComments"],ua=["||","&&","??"],pa=["++","--"],fa=[">","<",">=","<="],ga=["==","===","!=","!=="],ya=[].concat(ga,["in","instanceof"]),ma=[].concat(b(ya),fa),ha=["-","/","%","*","**","&","|",">>",">>>","<<","^"],ba=["+"].concat(ha,b(ma),["|>"]),xa=["=","+="].concat(b(ha.map(function(e){return e+"="})),b(ua.map(function(e){return e+"="}))),va=["delete","!"],Ra=["+","-","~"],ja=["typeof"],wa=["void","throw"].concat(va,Ra,ja),Ea={optional:["typeAnnotation","typeParameters","returnType"],force:["start","loc","end"]};e.BLOCK_SCOPED_SYMBOL=Symbol.for("var used to be block scoped"),e.NOT_LOCAL_BINDING=Symbol.for("should not be considered a local binding");var Sa={},Ta={},Pa={},Aa={},ka={},Ca={},_a={};function Ia(e){return Array.isArray(e)?"array":null===e?"null":typeof e}function Da(e){return{validate:e}}function Na(){return Da(Wa.apply(void 0,arguments))}function Oa(e){return{validate:e,optional:!0}}function Ba(){return{validate:Wa.apply(void 0,arguments),optional:!0}}function Ma(e){return za(Ha("array"),Ua(e))}function Fa(){return Ma(Wa.apply(void 0,arguments))}function La(){return Da(Fa.apply(void 0,arguments))}function Ua(e){var t=K.env.BABEL_TYPES_8_BREAKING?ns:function(){};function r(r,a,n){if(Array.isArray(n))for(var s=0,o={toString:function(){return a+"["+s+"]"}};s=2&&"type"in t[0]&&"array"===t[0].type&&!("each"in t[1]))throw new Error('An assertValueType("array") validator can only be followed by an assertEach(...) validator.');return a}var Xa,Ja,Ya,$a=new Set(["aliases","builder","deprecatedAlias","fields","inherits","visitor","validate"]),Qa=new Set(["default","optional","deprecated","validate"]),Za={};function en(){for(var e=arguments.length,t=new Array(e),r=0;r0:c&&"object"==typeof c)throw new Error("field defaults can only be primitives or empty arrays currently");a[o]={default:Array.isArray(c)?[]:c,optional:d.optional,deprecated:d.deprecated,validate:d.validate}}for(var l=t.visitor||r.visitor||[],u=t.aliases||r.aliases||[],p=t.builder||r.builder||t.visitor||[],f=0,g=Object.keys(t);f+s+1)throw new TypeError("RestElement must be last element of "+n)}:void 0}),rn("ReturnStatement",{visitor:["argument"],aliases:["Statement","Terminatorless","CompletionStatement"],fields:{argument:{validate:Wa("Expression"),optional:!0}}}),rn("SequenceExpression",{visitor:["expressions"],fields:{expressions:La("Expression")},aliases:["Expression"]}),rn("ParenthesizedExpression",{visitor:["expression"],aliases:["Expression","ExpressionWrapper"],fields:{expression:{validate:Wa("Expression")}}}),rn("SwitchCase",{visitor:["test","consequent"],fields:{test:{validate:Wa("Expression"),optional:!0},consequent:La("Statement")}}),rn("SwitchStatement",{visitor:["discriminant","cases"],aliases:["Statement","BlockParent","Scopable"],fields:{discriminant:{validate:Wa("Expression")},cases:La("SwitchCase")}}),rn("ThisExpression",{aliases:["Expression"]}),rn("ThrowStatement",{visitor:["argument"],aliases:["Statement","Terminatorless","CompletionStatement"],fields:{argument:{validate:Wa("Expression")}}}),rn("TryStatement",{visitor:["block","handler","finalizer"],aliases:["Statement"],fields:{block:{validate:K.env.BABEL_TYPES_8_BREAKING?za(Wa("BlockStatement"),Object.assign(function(e){if(!e.handler&&!e.finalizer)throw new TypeError("TryStatement expects either a handler or finalizer, or both")},{oneOfNodeTypes:["BlockStatement"]})):Wa("BlockStatement")},handler:{optional:!0,validate:Wa("CatchClause")},finalizer:{optional:!0,validate:Wa("BlockStatement")}}}),rn("UnaryExpression",{builder:["operator","argument","prefix"],fields:{prefix:{default:!0},argument:{validate:Wa("Expression")},operator:{validate:qa.apply(void 0,b(wa))}},visitor:["argument"],aliases:["UnaryLike","Expression"]}),rn("UpdateExpression",{builder:["operator","argument","prefix"],fields:{prefix:{default:!1},argument:{validate:K.env.BABEL_TYPES_8_BREAKING?Wa("Identifier","MemberExpression"):Wa("Expression")},operator:{validate:qa.apply(void 0,b(pa))}},visitor:["argument"],aliases:["Expression"]}),rn("VariableDeclaration",{builder:["kind","declarations"],visitor:["declarations"],aliases:["Statement","Declaration"],fields:{declare:{validate:Ha("boolean"),optional:!0},kind:{validate:qa("var","let","const","using","await using")},declarations:La("VariableDeclarator")},validate:K.env.BABEL_TYPES_8_BREAKING?(ln=Wa("Identifier","Placeholder"),un=Wa("Identifier","ArrayPattern","ObjectPattern","Placeholder"),pn=Wa("Identifier","VoidPattern","Placeholder"),function(e,t,r){var a=r.kind,n=r.declarations,s=Ir("ForXStatement",e,{left:r});if(s&&1!==n.length)throw new TypeError("Exactly one VariableDeclarator is required in the VariableDeclaration of a "+e.type);for(var o,d=i(n);!(o=d()).done;){var c=o.value;"const"===a||"let"===a||"var"===a?s||c.init?un(c,"id",c.id):ln(c,"id",c.id):pn(c,"id",c.id)}}):void 0}),rn("VariableDeclarator",{visitor:["id","init"],fields:{id:{validate:K.env.BABEL_TYPES_8_BREAKING?Wa("Identifier","ArrayPattern","ObjectPattern","VoidPattern"):Wa("LVal","VoidPattern")},definite:{optional:!0,validate:Ha("boolean")},init:{optional:!0,validate:Wa("Expression")}}}),rn("WhileStatement",{visitor:["test","body"],aliases:["Statement","BlockParent","Loop","While","Scopable"],fields:{test:{validate:Wa("Expression")},body:{validate:Wa("Statement")}}}),rn("WithStatement",{visitor:["object","body"],aliases:["Statement"],fields:{object:{validate:Wa("Expression")},body:{validate:Wa("Statement")}}}),rn("AssignmentPattern",{visitor:["left","right","decorators"],builder:["left","right"],aliases:["FunctionParameter","Pattern","PatternLike","LVal"],fields:Object.assign({},fn(),{left:{validate:Wa("Identifier","ObjectPattern","ArrayPattern","MemberExpression","TSAsExpression","TSSatisfiesExpression","TSTypeAssertion","TSNonNullExpression")},right:{validate:Wa("Expression")},decorators:{validate:Fa("Decorator"),optional:!0}})}),rn("ArrayPattern",{visitor:["elements","typeAnnotation"],builder:["elements"],aliases:["FunctionParameter","Pattern","PatternLike","LVal"],fields:Object.assign({},fn(),{elements:{validate:za(Ha("array"),Ua(Va("null","PatternLike")))}})}),rn("ArrowFunctionExpression",{builder:["params","body","async"],visitor:["typeParameters","params","predicate","returnType","body"],aliases:["Scopable","Function","BlockParent","FunctionParent","Expression","Pureish"],fields:Object.assign({},an(),nn(),{expression:{validate:Ha("boolean")},body:{validate:Wa("BlockStatement","Expression")},predicate:{validate:Wa("DeclaredPredicate","InferredPredicate"),optional:!0}})}),rn("ClassBody",{visitor:["body"],fields:{body:La("ClassMethod","ClassPrivateMethod","ClassProperty","ClassPrivateProperty","ClassAccessorProperty","TSDeclareMethod","TSIndexSignature","StaticBlock")}}),rn("ClassExpression",{builder:["id","superClass","body","decorators"],visitor:["decorators","id","typeParameters","superClass","superTypeParameters","mixins","implements","body"],aliases:["Scopable","Class","Expression"],fields:(Xa={id:{validate:Wa("Identifier"),optional:!0},typeParameters:{validate:Wa("TypeParameterDeclaration","TSTypeParameterDeclaration","Noop"),optional:!0},body:{validate:Wa("ClassBody")},superClass:{optional:!0,validate:Wa("Expression")}},Xa.superTypeParameters={validate:Wa("TypeParameterInstantiation","TSTypeParameterInstantiation"),optional:!0},Xa.implements={validate:Fa("TSExpressionWithTypeArguments","ClassImplements"),optional:!0},Xa.decorators={validate:Fa("Decorator"),optional:!0},Xa.mixins={validate:Wa("InterfaceExtends"),optional:!0},Xa)}),rn("ClassDeclaration",{inherits:"ClassExpression",aliases:["Scopable","Class","Statement","Declaration"],fields:(Ja={id:{validate:Wa("Identifier"),optional:!0},typeParameters:{validate:Wa("TypeParameterDeclaration","TSTypeParameterDeclaration","Noop"),optional:!0},body:{validate:Wa("ClassBody")},superClass:{optional:!0,validate:Wa("Expression")}},Ja.superTypeParameters={validate:Wa("TypeParameterInstantiation","TSTypeParameterInstantiation"),optional:!0},Ja.implements={validate:Fa("TSExpressionWithTypeArguments","ClassImplements"),optional:!0},Ja.decorators={validate:Fa("Decorator"),optional:!0},Ja.mixins={validate:Wa("InterfaceExtends"),optional:!0},Ja.declare={validate:Ha("boolean"),optional:!0},Ja.abstract={validate:Ha("boolean"),optional:!0},Ja),validate:K.env.BABEL_TYPES_8_BREAKING?function(){var e=Wa("Identifier");return function(t,r,a){Ir("ExportDefaultDeclaration",t)||e(a,"id",a.id)}}():void 0});var gn,yn,mn={attributes:{optional:!0,validate:Fa("ImportAttribute")},assertions:{deprecated:!0,optional:!0,validate:Fa("ImportAttribute")}};rn("ExportAllDeclaration",{builder:["source"],visitor:["source","attributes","assertions"],aliases:["Statement","Declaration","ImportOrExportDeclaration","ExportDeclaration"],fields:Object.assign({source:{validate:Wa("StringLiteral")},exportKind:Oa(qa("type","value"))},mn)}),rn("ExportDefaultDeclaration",{visitor:["declaration"],aliases:["Statement","Declaration","ImportOrExportDeclaration","ExportDeclaration"],fields:{declaration:Na("TSDeclareFunction","FunctionDeclaration","ClassDeclaration","Expression"),exportKind:Oa(qa("value"))}}),rn("ExportNamedDeclaration",{builder:["declaration","specifiers","source"],visitor:["declaration","specifiers","source","attributes","assertions"],aliases:["Statement","Declaration","ImportOrExportDeclaration","ExportDeclaration"],fields:Object.assign({declaration:{optional:!0,validate:K.env.BABEL_TYPES_8_BREAKING?za(Wa("Declaration"),Object.assign(function(e,t,r){if(r&&e.specifiers.length)throw new TypeError("Only declaration or specifiers is allowed on ExportNamedDeclaration");if(r&&e.source)throw new TypeError("Cannot export a declaration from a source")},{oneOfNodeTypes:["Declaration"]})):Wa("Declaration")}},mn,{specifiers:{default:[],validate:Ma((gn=Wa("ExportSpecifier","ExportDefaultSpecifier","ExportNamespaceSpecifier"),yn=Wa("ExportSpecifier"),K.env.BABEL_TYPES_8_BREAKING?Object.assign(function(e,t,r){(e.source?gn:yn)(e,t,r)},{oneOfNodeTypes:["ExportSpecifier","ExportDefaultSpecifier","ExportNamespaceSpecifier"]}):gn))},source:{validate:Wa("StringLiteral"),optional:!0},exportKind:Oa(qa("type","value"))})}),rn("ExportSpecifier",{visitor:["local","exported"],aliases:["ModuleSpecifier"],fields:{local:{validate:Wa("Identifier")},exported:{validate:Wa("Identifier","StringLiteral")},exportKind:{validate:qa("type","value"),optional:!0}}}),rn("ForOfStatement",{visitor:["left","right","body"],builder:["left","right","body","await"],aliases:["Scopable","Statement","For","BlockParent","Loop","ForXStatement"],fields:{left:{validate:function(){if(!K.env.BABEL_TYPES_8_BREAKING)return Wa("VariableDeclaration","LVal");var e=Wa("VariableDeclaration"),t=Wa("Identifier","MemberExpression","ArrayPattern","ObjectPattern","TSAsExpression","TSSatisfiesExpression","TSTypeAssertion","TSNonNullExpression");return Object.assign(function(r,a,n){Ir("VariableDeclaration",n)?e(r,a,n):t(r,a,n)},{oneOfNodeTypes:["VariableDeclaration","Identifier","MemberExpression","ArrayPattern","ObjectPattern","TSAsExpression","TSSatisfiesExpression","TSTypeAssertion","TSNonNullExpression"]})}()},right:{validate:Wa("Expression")},body:{validate:Wa("Statement")},await:{default:!1}}}),rn("ImportDeclaration",{builder:["specifiers","source"],visitor:["specifiers","source","attributes","assertions"],aliases:["Statement","Declaration","ImportOrExportDeclaration"],fields:Object.assign({},mn,{module:{optional:!0,validate:Ha("boolean")},phase:{default:null,validate:qa("source","defer")},specifiers:La("ImportSpecifier","ImportDefaultSpecifier","ImportNamespaceSpecifier"),source:{validate:Wa("StringLiteral")},importKind:{validate:qa("type","typeof","value"),optional:!0}})}),rn("ImportDefaultSpecifier",{visitor:["local"],aliases:["ModuleSpecifier"],fields:{local:{validate:Wa("Identifier")}}}),rn("ImportNamespaceSpecifier",{visitor:["local"],aliases:["ModuleSpecifier"],fields:{local:{validate:Wa("Identifier")}}}),rn("ImportSpecifier",{visitor:["imported","local"],builder:["local","imported"],aliases:["ModuleSpecifier"],fields:{local:{validate:Wa("Identifier")},imported:{validate:Wa("Identifier","StringLiteral")},importKind:{validate:qa("type","typeof","value"),optional:!0}}}),rn("ImportExpression",{visitor:["source","options"],aliases:["Expression"],fields:{phase:{default:null,validate:qa("source","defer")},source:{validate:Wa("Expression")},options:{validate:Wa("Expression"),optional:!0}}}),rn("MetaProperty",{visitor:["meta","property"],aliases:["Expression"],fields:{meta:{validate:K.env.BABEL_TYPES_8_BREAKING?za(Wa("Identifier"),Object.assign(function(e,t,r){var a;switch(r.name){case"function":a="sent";break;case"new":a="target";break;case"import":a="meta"}if(!Ir("Identifier",e.property,{name:a}))throw new TypeError("Unrecognised MetaProperty")},{oneOfNodeTypes:["Identifier"]})):Wa("Identifier")},property:{validate:Wa("Identifier")}}});var hn=function(){return{abstract:{validate:Ha("boolean"),optional:!0},accessibility:{validate:qa("public","private","protected"),optional:!0},static:{default:!1},override:{default:!1},computed:{default:!1},optional:{validate:Ha("boolean"),optional:!0},key:{validate:za(function(){var e=Wa("Identifier","StringLiteral","NumericLiteral","BigIntLiteral"),t=Wa("Expression");return function(r,a,n){(r.computed?t:e)(r,a,n)}}(),Wa("Identifier","StringLiteral","NumericLiteral","BigIntLiteral","Expression"))}}},bn=function(){return Object.assign({},an(),hn(),{params:La("FunctionParameter","TSParameterProperty"),kind:{validate:qa("get","set","method","constructor"),default:"method"},access:{validate:za(Ha("string"),qa("public","private","protected")),optional:!0},decorators:{validate:Fa("Decorator"),optional:!0}})};rn("ClassMethod",{aliases:["Function","Scopable","BlockParent","FunctionParent","Method"],builder:["kind","key","params","body","computed","static","generator","async"],visitor:["decorators","key","typeParameters","params","returnType","body"],fields:Object.assign({},bn(),nn(),{body:{validate:Wa("BlockStatement")}})}),rn("ObjectPattern",{visitor:["decorators","properties","typeAnnotation"],builder:["properties"],aliases:["FunctionParameter","Pattern","PatternLike","LVal"],fields:Object.assign({},fn(),{properties:La("RestElement","ObjectProperty")})}),rn("SpreadElement",{visitor:["argument"],aliases:["UnaryLike"],deprecatedAlias:"SpreadProperty",fields:{argument:{validate:Wa("Expression")}}}),rn("Super",{aliases:["Expression"]}),rn("TaggedTemplateExpression",{visitor:["tag","typeParameters","quasi"],builder:["tag","quasi"],aliases:["Expression"],fields:(Ya={tag:{validate:Wa("Expression")},quasi:{validate:Wa("TemplateLiteral")}},Ya.typeParameters={validate:Wa("TypeParameterInstantiation","TSTypeParameterInstantiation"),optional:!0},Ya)}),rn("TemplateElement",{builder:["value","tail"],fields:{value:{validate:za(function(e){var t=Object.keys(e);function r(r,a,n){for(var s,o=[],d=i(t);!(s=d()).done;){var c=s.value;try{as(r,c,n[c],e[c])}catch(e){if(e instanceof TypeError){o.push(e.message);continue}throw e}}if(o.length)throw new TypeError("Property "+a+" of "+r.type+" expected to have the following:\n"+o.join("\n"))}return r.shapeOf=e,r}({raw:{validate:Ha("string")},cooked:{validate:Ha("string"),optional:!0}}),function(e){var t=e.value.raw,r=!1,a=function(){throw new Error("Internal @babel/types error.")},n=aa("template",t,0,0,0,{unterminated:function(){r=!0},strictNumericEscape:a,invalidEscapeSequence:a,numericSeparatorInEscapeSequence:a,unexpectedNumericSeparator:a,invalidDigit:a,invalidCodePoint:a}),s=n.str,o=n.firstInvalidLoc;if(!r)throw new Error("Invalid raw");e.value.cooked=o?null:s})},tail:{default:!1}}}),rn("TemplateLiteral",{visitor:["quasis","expressions"],aliases:["Expression","Literal"],fields:{quasis:La("TemplateElement"),expressions:{validate:za(Ha("array"),Ua(Wa("Expression","TSType")),function(e,t,r){if(e.quasis.length!==r.length+1)throw new TypeError("Number of "+e.type+" quasis should be exactly one more than the number of expressions.\nExpected "+(r.length+1)+" quasis but got "+e.quasis.length)})}}}),rn("YieldExpression",{builder:["argument","delegate"],visitor:["argument"],aliases:["Expression","Terminatorless"],fields:{delegate:{validate:K.env.BABEL_TYPES_8_BREAKING?za(Ha("boolean"),Object.assign(function(e,t,r){if(r&&!e.argument)throw new TypeError("Property delegate of YieldExpression cannot be true if there is no argument")},{type:"boolean"})):Ha("boolean"),default:!1},argument:{optional:!0,validate:Wa("Expression")}}}),rn("AwaitExpression",{builder:["argument"],visitor:["argument"],aliases:["Expression","Terminatorless"],fields:{argument:{validate:Wa("Expression")}}}),rn("Import",{aliases:["Expression"]}),rn("BigIntLiteral",{builder:["value"],fields:{value:{validate:Ha("string")}},aliases:["Expression","Pureish","Literal","Immutable"]}),rn("ExportNamespaceSpecifier",{visitor:["exported"],aliases:["ModuleSpecifier"],fields:{exported:{validate:Wa("Identifier")}}}),rn("OptionalMemberExpression",{builder:["object","property","computed","optional"],visitor:["object","property"],aliases:["Expression"],fields:{object:{validate:Wa("Expression")},property:{validate:function(){var e=Wa("Identifier"),t=Wa("Expression"),r=Object.assign(function(r,a,n){(r.computed?t:e)(r,a,n)},{oneOfNodeTypes:["Expression","Identifier"]});return r}()},computed:{default:!1},optional:{validate:K.env.BABEL_TYPES_8_BREAKING?za(Ha("boolean"),Ka()):Ha("boolean")}}}),rn("OptionalCallExpression",{visitor:["callee","typeParameters","typeArguments","arguments"],builder:["callee","arguments","optional"],aliases:["Expression"],fields:Object.assign({callee:{validate:Wa("Expression")},arguments:La("Expression","SpreadElement","ArgumentPlaceholder"),optional:{validate:K.env.BABEL_TYPES_8_BREAKING?za(Ha("boolean"),Ka()):Ha("boolean")},typeArguments:{validate:Wa("TypeParameterInstantiation"),optional:!0}},{typeParameters:{validate:Wa("TSTypeParameterInstantiation"),optional:!0}})}),rn("ClassProperty",{visitor:["decorators","variance","key","typeAnnotation","value"],builder:["key","value","typeAnnotation","decorators","computed","static"],aliases:["Property"],fields:Object.assign({},hn(),{value:{validate:Wa("Expression"),optional:!0},definite:{validate:Ha("boolean"),optional:!0},typeAnnotation:{validate:Wa("TypeAnnotation","TSTypeAnnotation","Noop"),optional:!0},decorators:{validate:Fa("Decorator"),optional:!0},readonly:{validate:Ha("boolean"),optional:!0},declare:{validate:Ha("boolean"),optional:!0},variance:{validate:Wa("Variance"),optional:!0}})}),rn("ClassAccessorProperty",{visitor:["decorators","key","typeAnnotation","value"],builder:["key","value","typeAnnotation","decorators","computed","static"],aliases:["Property","Accessor"],fields:Object.assign({},hn(),{key:{validate:za(function(){var e=Wa("Identifier","StringLiteral","NumericLiteral","BigIntLiteral","PrivateName"),t=Wa("Expression");return function(r,a,n){(r.computed?t:e)(r,a,n)}}(),Wa("Identifier","StringLiteral","NumericLiteral","BigIntLiteral","Expression","PrivateName"))},value:{validate:Wa("Expression"),optional:!0},definite:{validate:Ha("boolean"),optional:!0},typeAnnotation:{validate:Wa("TypeAnnotation","TSTypeAnnotation","Noop"),optional:!0},decorators:{validate:Fa("Decorator"),optional:!0},readonly:{validate:Ha("boolean"),optional:!0},declare:{validate:Ha("boolean"),optional:!0},variance:{validate:Wa("Variance"),optional:!0}})}),rn("ClassPrivateProperty",{visitor:["decorators","variance","key","typeAnnotation","value"],builder:["key","value","decorators","static"],aliases:["Property","Private"],fields:{key:{validate:Wa("PrivateName")},value:{validate:Wa("Expression"),optional:!0},typeAnnotation:{validate:Wa("TypeAnnotation","TSTypeAnnotation","Noop"),optional:!0},decorators:{validate:Fa("Decorator"),optional:!0},static:{validate:Ha("boolean"),default:!1},readonly:{validate:Ha("boolean"),optional:!0},optional:{validate:Ha("boolean"),optional:!0},definite:{validate:Ha("boolean"),optional:!0},variance:{validate:Wa("Variance"),optional:!0}}}),rn("ClassPrivateMethod",{builder:["kind","key","params","body","static"],visitor:["decorators","key","typeParameters","params","returnType","body"],aliases:["Function","Scopable","BlockParent","FunctionParent","Method","Private"],fields:Object.assign({},bn(),nn(),{kind:{validate:qa("get","set","method"),default:"method"},key:{validate:Wa("PrivateName")},body:{validate:Wa("BlockStatement")}})}),rn("PrivateName",{visitor:["id"],aliases:["Private"],fields:{id:{validate:Wa("Identifier")}}}),rn("StaticBlock",{visitor:["body"],fields:{body:La("Statement")},aliases:["Scopable","BlockParent","FunctionParent"]}),rn("ImportAttribute",{visitor:["key","value"],fields:{key:{validate:Wa("Identifier","StringLiteral")},value:{validate:Wa("StringLiteral")}}});var xn=en("Flow"),vn=function(e){var t="DeclareClass"===e;xn(e,{builder:["id","typeParameters","extends","body"],visitor:["id","typeParameters","extends"].concat(b(t?["mixins","implements"]:[]),["body"]),aliases:["FlowDeclaration","Statement","Declaration"],fields:Object.assign({id:Na("Identifier"),typeParameters:Ba("TypeParameterDeclaration"),extends:Oa(Fa("InterfaceExtends"))},t?{mixins:Oa(Fa("InterfaceExtends")),implements:Oa(Fa("ClassImplements"))}:{},{body:Na("ObjectTypeAnnotation")})})};xn("AnyTypeAnnotation",{aliases:["FlowType","FlowBaseAnnotation"]}),xn("ArrayTypeAnnotation",{visitor:["elementType"],aliases:["FlowType"],fields:{elementType:Na("FlowType")}}),xn("BooleanTypeAnnotation",{aliases:["FlowType","FlowBaseAnnotation"]}),xn("BooleanLiteralTypeAnnotation",{builder:["value"],aliases:["FlowType"],fields:{value:Da(Ha("boolean"))}}),xn("NullLiteralTypeAnnotation",{aliases:["FlowType","FlowBaseAnnotation"]}),xn("ClassImplements",{visitor:["id","typeParameters"],fields:{id:Na("Identifier"),typeParameters:Ba("TypeParameterInstantiation")}}),vn("DeclareClass"),xn("DeclareFunction",{builder:["id"],visitor:["id","predicate"],aliases:["FlowDeclaration","Statement","Declaration"],fields:{id:Na("Identifier"),predicate:Ba("DeclaredPredicate")}}),vn("DeclareInterface"),xn("DeclareModule",{builder:["id","body","kind"],visitor:["id","body"],aliases:["FlowDeclaration","Statement","Declaration"],fields:{id:Na("Identifier","StringLiteral"),body:Na("BlockStatement"),kind:Oa(qa("CommonJS","ES"))}}),xn("DeclareModuleExports",{visitor:["typeAnnotation"],aliases:["FlowDeclaration","Statement","Declaration"],fields:{typeAnnotation:Na("TypeAnnotation")}}),xn("DeclareTypeAlias",{visitor:["id","typeParameters","right"],aliases:["FlowDeclaration","Statement","Declaration"],fields:{id:Na("Identifier"),typeParameters:Ba("TypeParameterDeclaration"),right:Na("FlowType")}}),xn("DeclareOpaqueType",{visitor:["id","typeParameters","supertype"],aliases:["FlowDeclaration","Statement","Declaration"],fields:{id:Na("Identifier"),typeParameters:Ba("TypeParameterDeclaration"),supertype:Ba("FlowType"),impltype:Ba("FlowType")}}),xn("DeclareVariable",{visitor:["id"],aliases:["FlowDeclaration","Statement","Declaration"],fields:{id:Na("Identifier")}}),xn("DeclareExportDeclaration",{visitor:["declaration","specifiers","source","attributes"],aliases:["FlowDeclaration","Statement","Declaration"],fields:Object.assign({declaration:Ba("Flow"),specifiers:Oa(Fa("ExportSpecifier","ExportNamespaceSpecifier")),source:Ba("StringLiteral"),default:Oa(Ha("boolean"))},mn)}),xn("DeclareExportAllDeclaration",{visitor:["source","attributes"],aliases:["FlowDeclaration","Statement","Declaration"],fields:Object.assign({source:Na("StringLiteral"),exportKind:Oa(qa("type","value"))},mn)}),xn("DeclaredPredicate",{visitor:["value"],aliases:["FlowPredicate"],fields:{value:Na("Flow")}}),xn("ExistsTypeAnnotation",{aliases:["FlowType"]}),xn("FunctionTypeAnnotation",{builder:["typeParameters","params","rest","returnType"],visitor:["typeParameters","this","params","rest","returnType"],aliases:["FlowType"],fields:{typeParameters:Ba("TypeParameterDeclaration"),params:La("FunctionTypeParam"),rest:Ba("FunctionTypeParam"),this:Ba("FunctionTypeParam"),returnType:Na("FlowType")}}),xn("FunctionTypeParam",{visitor:["name","typeAnnotation"],fields:{name:Ba("Identifier"),typeAnnotation:Na("FlowType"),optional:Oa(Ha("boolean"))}}),xn("GenericTypeAnnotation",{visitor:["id","typeParameters"],aliases:["FlowType"],fields:{id:Na("Identifier","QualifiedTypeIdentifier"),typeParameters:Ba("TypeParameterInstantiation")}}),xn("InferredPredicate",{aliases:["FlowPredicate"]}),xn("InterfaceExtends",{visitor:["id","typeParameters"],fields:{id:Na("Identifier","QualifiedTypeIdentifier"),typeParameters:Ba("TypeParameterInstantiation")}}),vn("InterfaceDeclaration"),xn("InterfaceTypeAnnotation",{visitor:["extends","body"],aliases:["FlowType"],fields:{extends:Oa(Fa("InterfaceExtends")),body:Na("ObjectTypeAnnotation")}}),xn("IntersectionTypeAnnotation",{visitor:["types"],aliases:["FlowType"],fields:{types:Da(Fa("FlowType"))}}),xn("MixedTypeAnnotation",{aliases:["FlowType","FlowBaseAnnotation"]}),xn("EmptyTypeAnnotation",{aliases:["FlowType","FlowBaseAnnotation"]}),xn("NullableTypeAnnotation",{visitor:["typeAnnotation"],aliases:["FlowType"],fields:{typeAnnotation:Na("FlowType")}}),xn("NumberLiteralTypeAnnotation",{builder:["value"],aliases:["FlowType"],fields:{value:Da(Ha("number"))}}),xn("NumberTypeAnnotation",{aliases:["FlowType","FlowBaseAnnotation"]}),xn("ObjectTypeAnnotation",{visitor:["properties","indexers","callProperties","internalSlots"],aliases:["FlowType"],builder:["properties","indexers","callProperties","internalSlots","exact"],fields:{properties:Da(Fa("ObjectTypeProperty","ObjectTypeSpreadProperty")),indexers:{validate:Fa("ObjectTypeIndexer"),optional:!0,default:[]},callProperties:{validate:Fa("ObjectTypeCallProperty"),optional:!0,default:[]},internalSlots:{validate:Fa("ObjectTypeInternalSlot"),optional:!0,default:[]},exact:{validate:Ha("boolean"),default:!1},inexact:Oa(Ha("boolean"))}}),xn("ObjectTypeInternalSlot",{visitor:["id","value"],builder:["id","value","optional","static","method"],aliases:["UserWhitespacable"],fields:{id:Na("Identifier"),value:Na("FlowType"),optional:Da(Ha("boolean")),static:Da(Ha("boolean")),method:Da(Ha("boolean"))}}),xn("ObjectTypeCallProperty",{visitor:["value"],aliases:["UserWhitespacable"],fields:{value:Na("FlowType"),static:Da(Ha("boolean"))}}),xn("ObjectTypeIndexer",{visitor:["variance","id","key","value"],builder:["id","key","value","variance"],aliases:["UserWhitespacable"],fields:{id:Ba("Identifier"),key:Na("FlowType"),value:Na("FlowType"),static:Da(Ha("boolean")),variance:Ba("Variance")}}),xn("ObjectTypeProperty",{visitor:["key","value","variance"],aliases:["UserWhitespacable"],fields:{key:Na("Identifier","StringLiteral"),value:Na("FlowType"),kind:Da(qa("init","get","set")),static:Da(Ha("boolean")),proto:Da(Ha("boolean")),optional:Da(Ha("boolean")),variance:Ba("Variance"),method:Da(Ha("boolean"))}}),xn("ObjectTypeSpreadProperty",{visitor:["argument"],aliases:["UserWhitespacable"],fields:{argument:Na("FlowType")}}),xn("OpaqueType",{visitor:["id","typeParameters","supertype","impltype"],aliases:["FlowDeclaration","Statement","Declaration"],fields:{id:Na("Identifier"),typeParameters:Ba("TypeParameterDeclaration"),supertype:Ba("FlowType"),impltype:Na("FlowType")}}),xn("QualifiedTypeIdentifier",{visitor:["qualification","id"],builder:["id","qualification"],fields:{id:Na("Identifier"),qualification:Na("Identifier","QualifiedTypeIdentifier")}}),xn("StringLiteralTypeAnnotation",{builder:["value"],aliases:["FlowType"],fields:{value:Da(Ha("string"))}}),xn("StringTypeAnnotation",{aliases:["FlowType","FlowBaseAnnotation"]}),xn("SymbolTypeAnnotation",{aliases:["FlowType","FlowBaseAnnotation"]}),xn("ThisTypeAnnotation",{aliases:["FlowType","FlowBaseAnnotation"]}),xn("TupleTypeAnnotation",{visitor:["types"],aliases:["FlowType"],fields:{types:Da(Fa("FlowType"))}}),xn("TypeofTypeAnnotation",{visitor:["argument"],aliases:["FlowType"],fields:{argument:Na("FlowType")}}),xn("TypeAlias",{visitor:["id","typeParameters","right"],aliases:["FlowDeclaration","Statement","Declaration"],fields:{id:Na("Identifier"),typeParameters:Ba("TypeParameterDeclaration"),right:Na("FlowType")}}),xn("TypeAnnotation",{visitor:["typeAnnotation"],fields:{typeAnnotation:Na("FlowType")}}),xn("TypeCastExpression",{visitor:["expression","typeAnnotation"],aliases:["ExpressionWrapper","Expression"],fields:{expression:Na("Expression"),typeAnnotation:Na("TypeAnnotation")}}),xn("TypeParameter",{visitor:["bound","default","variance"],fields:{name:Da(Ha("string")),bound:Ba("TypeAnnotation"),default:Ba("FlowType"),variance:Ba("Variance")}}),xn("TypeParameterDeclaration",{visitor:["params"],fields:{params:Da(Fa("TypeParameter"))}}),xn("TypeParameterInstantiation",{visitor:["params"],fields:{params:Da(Fa("FlowType"))}}),xn("UnionTypeAnnotation",{visitor:["types"],aliases:["FlowType"],fields:{types:Da(Fa("FlowType"))}}),xn("Variance",{builder:["kind"],fields:{kind:Da(qa("minus","plus"))}}),xn("VoidTypeAnnotation",{aliases:["FlowType","FlowBaseAnnotation"]}),xn("EnumDeclaration",{aliases:["Statement","Declaration"],visitor:["id","body"],fields:{id:Na("Identifier"),body:Na("EnumBooleanBody","EnumNumberBody","EnumStringBody","EnumSymbolBody")}}),xn("EnumBooleanBody",{aliases:["EnumBody"],visitor:["members"],fields:{explicitType:Da(Ha("boolean")),members:La("EnumBooleanMember"),hasUnknownMembers:Da(Ha("boolean"))}}),xn("EnumNumberBody",{aliases:["EnumBody"],visitor:["members"],fields:{explicitType:Da(Ha("boolean")),members:La("EnumNumberMember"),hasUnknownMembers:Da(Ha("boolean"))}}),xn("EnumStringBody",{aliases:["EnumBody"],visitor:["members"],fields:{explicitType:Da(Ha("boolean")),members:La("EnumStringMember","EnumDefaultedMember"),hasUnknownMembers:Da(Ha("boolean"))}}),xn("EnumSymbolBody",{aliases:["EnumBody"],visitor:["members"],fields:{members:La("EnumDefaultedMember"),hasUnknownMembers:Da(Ha("boolean"))}}),xn("EnumBooleanMember",{aliases:["EnumMember"],builder:["id"],visitor:["id","init"],fields:{id:Na("Identifier"),init:Na("BooleanLiteral")}}),xn("EnumNumberMember",{aliases:["EnumMember"],visitor:["id","init"],fields:{id:Na("Identifier"),init:Na("NumericLiteral")}}),xn("EnumStringMember",{aliases:["EnumMember"],visitor:["id","init"],fields:{id:Na("Identifier"),init:Na("StringLiteral")}}),xn("EnumDefaultedMember",{aliases:["EnumMember"],visitor:["id"],fields:{id:Na("Identifier")}}),xn("IndexedAccessType",{visitor:["objectType","indexType"],aliases:["FlowType"],fields:{objectType:Na("FlowType"),indexType:Na("FlowType")}}),xn("OptionalIndexedAccessType",{visitor:["objectType","indexType"],aliases:["FlowType"],fields:{objectType:Na("FlowType"),indexType:Na("FlowType"),optional:Da(Ha("boolean"))}});var Rn=en("JSX");Rn("JSXAttribute",{visitor:["name","value"],aliases:["Immutable"],fields:{name:{validate:Wa("JSXIdentifier","JSXNamespacedName")},value:{optional:!0,validate:Wa("JSXElement","JSXFragment","StringLiteral","JSXExpressionContainer")}}}),Rn("JSXClosingElement",{visitor:["name"],aliases:["Immutable"],fields:{name:{validate:Wa("JSXIdentifier","JSXMemberExpression","JSXNamespacedName")}}}),Rn("JSXElement",{builder:["openingElement","closingElement","children","selfClosing"],visitor:["openingElement","children","closingElement"],aliases:["Immutable","Expression"],fields:Object.assign({openingElement:{validate:Wa("JSXOpeningElement")},closingElement:{optional:!0,validate:Wa("JSXClosingElement")},children:La("JSXText","JSXExpressionContainer","JSXSpreadChild","JSXElement","JSXFragment")},{selfClosing:{validate:Ha("boolean"),optional:!0}})}),Rn("JSXEmptyExpression",{}),Rn("JSXExpressionContainer",{visitor:["expression"],aliases:["Immutable"],fields:{expression:{validate:Wa("Expression","JSXEmptyExpression")}}}),Rn("JSXSpreadChild",{visitor:["expression"],aliases:["Immutable"],fields:{expression:{validate:Wa("Expression")}}}),Rn("JSXIdentifier",{builder:["name"],fields:{name:{validate:Ha("string")}}}),Rn("JSXMemberExpression",{visitor:["object","property"],fields:{object:{validate:Wa("JSXMemberExpression","JSXIdentifier")},property:{validate:Wa("JSXIdentifier")}}}),Rn("JSXNamespacedName",{visitor:["namespace","name"],fields:{namespace:{validate:Wa("JSXIdentifier")},name:{validate:Wa("JSXIdentifier")}}}),Rn("JSXOpeningElement",{builder:["name","attributes","selfClosing"],visitor:["name","typeParameters","typeArguments","attributes"],aliases:["Immutable"],fields:Object.assign({name:{validate:Wa("JSXIdentifier","JSXMemberExpression","JSXNamespacedName")},selfClosing:{default:!1},attributes:La("JSXAttribute","JSXSpreadAttribute"),typeArguments:{validate:Wa("TypeParameterInstantiation"),optional:!0}},{typeParameters:{validate:Wa("TSTypeParameterInstantiation"),optional:!0}})}),Rn("JSXSpreadAttribute",{visitor:["argument"],fields:{argument:{validate:Wa("Expression")}}}),Rn("JSXText",{aliases:["Immutable"],builder:["value"],fields:{value:{validate:Ha("string")}}}),Rn("JSXFragment",{builder:["openingFragment","closingFragment","children"],visitor:["openingFragment","children","closingFragment"],aliases:["Immutable","Expression"],fields:{openingFragment:{validate:Wa("JSXOpeningFragment")},closingFragment:{validate:Wa("JSXClosingFragment")},children:La("JSXText","JSXExpressionContainer","JSXSpreadChild","JSXElement","JSXFragment")}}),Rn("JSXOpeningFragment",{aliases:["Immutable"]}),Rn("JSXClosingFragment",{aliases:["Immutable"]});for(var jn=["Identifier","StringLiteral","Expression","Statement","Declaration","BlockStatement","ClassBody","Pattern"],wn={Declaration:["Statement"],Pattern:["PatternLike","LVal"]},En=0,Sn=jn;En=Number.MAX_SAFE_INTEGER?Am.uid=0:Am.uid++};var Cm=Function.call.bind(Object.prototype.toString);function _m(e){if(void 0===e)return ks("undefined");if(!0===e||!1===e)return Os(e);if(null===e)return{type:"NullLiteral"};if("string"==typeof e)return Is(e);if("number"==typeof e){var t;if(Number.isFinite(e))t=Ds(Math.abs(e));else t=ls("/",Number.isNaN(e)?Ds(0):Ds(1),Ds(0));return(e<0||Object.is(e,-0))&&(t=Zs("-",t)),t}if("bigint"==typeof e)return e<0?Zs("-",is(-e)):is(e);if(function(e){return"[object RegExp]"===Cm(e)}(e))return Bs(e.source,/\/([a-z]*)$/.exec(e.toString())[1]);if(Array.isArray(e))return ds(e.map(_m));if(function(e){if("object"!=typeof e||null===e||"[object Object]"!==Object.prototype.toString.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||null===Object.getPrototypeOf(t)}(e)){for(var r=[],a=0,n=Object.keys(e);a1?e:e[0]}),th=Zm(function(e){return e}),rh=Zm(function(e){if(0===e.length)throw new Error("Found nothing to return.");if(e.length>1)throw new Error("Found multiple statements but wanted one");return e[0]}),ah={code:function(e){return"(\n"+e+"\n)"},validate:function(e){if(e.program.body.length>1)throw new Error("Found multiple statements but wanted one");if(0===ah.unwrap(e).start)throw new Error("Parse result included parens.")},unwrap:function(e){var t=m(e.program.body,1)[0];return Qm(t),t.expression}},nh=["placeholderWhitelist","placeholderPattern","preserveComments","syntacticPlaceholders"];function sh(e,t){var r=t.placeholderWhitelist,a=void 0===r?e.placeholderWhitelist:r,n=t.placeholderPattern,s=void 0===n?e.placeholderPattern:n,o=t.preserveComments,i=void 0===o?e.preserveComments:o,d=t.syntacticPlaceholders,c=void 0===d?e.syntacticPlaceholders:d;return{parser:Object.assign({},e.parser,t.parser),placeholderWhitelist:a,placeholderPattern:s,preserveComments:i,syntacticPlaceholders:c}}function oh(e){if(null!=e&&"object"!=typeof e)throw new Error("Unknown template options.");var t=e||{},r=t.placeholderWhitelist,a=t.placeholderPattern,n=t.preserveComments,s=t.syntacticPlaceholders,o=u(t,nh);if(null!=r&&!(r instanceof Set))throw new Error("'.placeholderWhitelist' must be a Set, null, or undefined");if(null!=a&&!(a instanceof RegExp)&&!1!==a)throw new Error("'.placeholderPattern' must be a RegExp, false, null, or undefined");if(null!=n&&"boolean"!=typeof n)throw new Error("'.preserveComments' must be a boolean, null, or undefined");if(null!=s&&"boolean"!=typeof s)throw new Error("'.syntacticPlaceholders' must be a boolean, null, or undefined");if(!0===s&&(null!=r||null!=a))throw new Error("'.placeholderWhitelist' and '.placeholderPattern' aren't compatible with '.syntacticPlaceholders: true'");return{parser:o,placeholderWhitelist:r||void 0,placeholderPattern:null==a?void 0:a,preserveComments:null==n?void 0:n,syntacticPlaceholders:null==s?void 0:s}}function ih(e){if(Array.isArray(e))return e.reduce(function(e,t,r){return e["$"+r]=t,e},{});if("object"==typeof e||null==e)return e||void 0;throw new Error("Template replacements must be an array, object, null, or undefined")}var dh=o(function(e,t,r){this.line=void 0,this.column=void 0,this.index=void 0,this.line=e,this.column=t,this.index=r}),ch=o(function(e,t){this.start=void 0,this.end=void 0,this.filename=void 0,this.identifierName=void 0,this.start=e,this.end=t});function lh(e,t){var r=e.line,a=e.column,n=e.index;return new dh(r,a+t,n+t)}var uh,ph="BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED",fh={ImportMetaOutsideModule:{message:"import.meta may appear only with 'sourceType: \"module\"'",code:ph},ImportOutsideModule:{message:"'import' and 'export' may appear only with 'sourceType: \"module\"'",code:ph}},gh={ArrayPattern:"array destructuring pattern",AssignmentExpression:"assignment expression",AssignmentPattern:"assignment expression",ArrowFunctionExpression:"arrow function expression",ConditionalExpression:"conditional expression",CatchClause:"catch clause",ForOfStatement:"for-of statement",ForInStatement:"for-in statement",ForStatement:"for-loop",FormalParameters:"function parameter list",Identifier:"identifier",ImportSpecifier:"import specifier",ImportDefaultSpecifier:"import default specifier",ImportNamespaceSpecifier:"import namespace specifier",ObjectPattern:"object destructuring pattern",ParenthesizedExpression:"parenthesized expression",RestElement:"rest element",UpdateExpression:{true:"prefix operation",false:"postfix operation"},VariableDeclarator:"variable declaration",YieldExpression:"yield expression"},yh=function(e){return"UpdateExpression"===e.type?gh.UpdateExpression[""+e.prefix]:gh[e.type]},mh={AccessorIsGenerator:function(e){return"A "+e.kind+"ter cannot be a generator."},ArgumentsInClass:"'arguments' is only allowed in functions and class methods.",AsyncFunctionInSingleStatementContext:"Async functions can only be declared at the top level or inside a block.",AwaitBindingIdentifier:"Can not use 'await' as identifier inside an async function.",AwaitBindingIdentifierInStaticBlock:"Can not use 'await' as identifier inside a static block.",AwaitExpressionFormalParameter:"'await' is not allowed in async function parameters.",AwaitUsingNotInAsyncContext:"'await using' is only allowed within async functions and at the top levels of modules.",AwaitNotInAsyncContext:"'await' is only allowed within async functions and at the top levels of modules.",BadGetterArity:"A 'get' accessor must not have any formal parameters.",BadSetterArity:"A 'set' accessor must have exactly one formal parameter.",BadSetterRestParameter:"A 'set' accessor function argument must not be a rest parameter.",ConstructorClassField:"Classes may not have a field named 'constructor'.",ConstructorClassPrivateField:"Classes may not have a private field named '#constructor'.",ConstructorIsAccessor:"Class constructor may not be an accessor.",ConstructorIsAsync:"Constructor can't be an async function.",ConstructorIsGenerator:"Constructor can't be a generator.",DeclarationMissingInitializer:function(e){return"Missing initializer in "+e.kind+" declaration."},DecoratorArgumentsOutsideParentheses:"Decorator arguments must be moved inside parentheses: use '@(decorator(args))' instead of '@(decorator)(args)'.",DecoratorBeforeExport:"Decorators must be placed *before* the 'export' keyword. Remove the 'decoratorsBeforeExport: true' option to use the 'export @decorator class {}' syntax.",DecoratorsBeforeAfterExport:"Decorators can be placed *either* before or after the 'export' keyword, but not in both locations at the same time.",DecoratorConstructor:"Decorators can't be used with a constructor. Did you mean '@dec class { ... }'?",DecoratorExportClass:"Decorators must be placed *after* the 'export' keyword. Remove the 'decoratorsBeforeExport: false' option to use the '@decorator export class {}' syntax.",DecoratorSemicolon:"Decorators must not be followed by a semicolon.",DecoratorStaticBlock:"Decorators can't be used with a static block.",DeferImportRequiresNamespace:'Only `import defer * as x from "./module"` is valid.',DeletePrivateField:"Deleting a private field is not allowed.",DestructureNamedImport:"ES2015 named imports do not destructure. Use another statement for destructuring after the import.",DuplicateConstructor:"Duplicate constructor in the same class.",DuplicateDefaultExport:"Only one default export allowed per module.",DuplicateExport:function(e){return"`"+e.exportName+"` has already been exported. Exported identifiers must be unique."},DuplicateProto:"Redefinition of __proto__ property.",DuplicateRegExpFlags:"Duplicate regular expression flag.",ElementAfterRest:"Rest element must be last element.",EscapedCharNotAnIdentifier:"Invalid Unicode escape.",ExportBindingIsString:function(e){return"A string literal cannot be used as an exported binding without `from`.\n- Did you mean `export { '"+e.localName+"' as '"+e.exportName+"' } from 'some-module'`?"},ExportDefaultFromAsIdentifier:"'from' is not allowed as an identifier after 'export default'.",ForInOfLoopInitializer:function(e){return"'"+("ForInStatement"===e.type?"for-in":"for-of")+"' loop variable declaration may not have an initializer."},ForInUsing:"For-in loop may not start with 'using' declaration.",ForOfAsync:"The left-hand side of a for-of loop may not be 'async'.",ForOfLet:"The left-hand side of a for-of loop may not start with 'let'.",GeneratorInSingleStatementContext:"Generators can only be declared at the top level or inside a block.",IllegalBreakContinue:function(e){return"Unsyntactic "+("BreakStatement"===e.type?"break":"continue")+"."},IllegalLanguageModeDirective:"Illegal 'use strict' directive in function with non-simple parameter list.",IllegalReturn:"'return' outside of function.",ImportAttributesUseAssert:"The `assert` keyword in import attributes is deprecated and it has been replaced by the `with` keyword. You can enable the `deprecatedImportAssert` parser plugin to suppress this error.",ImportBindingIsString:function(e){return'A string literal cannot be used as an imported binding.\n- Did you mean `import { "'+e.importName+'" as foo }`?'},ImportCallArity:"`import()` requires exactly one or two arguments.",ImportCallNotNewExpression:"Cannot use new with import(...).",ImportCallSpreadArgument:"`...` is not allowed in `import()`.",ImportJSONBindingNotDefault:"A JSON module can only be imported with `default`.",ImportReflectionHasAssertion:"`import module x` cannot have assertions.",ImportReflectionNotBinding:'Only `import module x from "./module"` is valid.',IncompatibleRegExpUVFlags:"The 'u' and 'v' regular expression flags cannot be enabled at the same time.",InvalidBigIntLiteral:"Invalid BigIntLiteral.",InvalidCodePoint:"Code point out of bounds.",InvalidCoverDiscardElement:"'void' must be followed by an expression when not used in a binding position.",InvalidCoverInitializedName:"Invalid shorthand property initializer.",InvalidDecimal:"Invalid decimal.",InvalidDigit:function(e){return"Expected number in radix "+e.radix+"."},InvalidEscapeSequence:"Bad character escape sequence.",InvalidEscapeSequenceTemplate:"Invalid escape sequence in template.",InvalidEscapedReservedWord:function(e){return"Escape sequence in keyword "+e.reservedWord+"."},InvalidIdentifier:function(e){return"Invalid identifier "+e.identifierName+"."},InvalidLhs:function(e){var t=e.ancestor;return"Invalid left-hand side in "+yh(t)+"."},InvalidLhsBinding:function(e){var t=e.ancestor;return"Binding invalid left-hand side in "+yh(t)+"."},InvalidLhsOptionalChaining:function(e){var t=e.ancestor;return"Invalid optional chaining in the left-hand side of "+yh(t)+"."},InvalidNumber:"Invalid number.",InvalidOrMissingExponent:"Floating-point numbers require a valid exponent after the 'e'.",InvalidOrUnexpectedToken:function(e){return"Unexpected character '"+e.unexpected+"'."},InvalidParenthesizedAssignment:"Invalid parenthesized assignment pattern.",InvalidPrivateFieldResolution:function(e){return"Private name #"+e.identifierName+" is not defined."},InvalidPropertyBindingPattern:"Binding member expression.",InvalidRecordProperty:"Only properties and spread elements are allowed in record definitions.",InvalidRestAssignmentPattern:"Invalid rest operator's argument.",LabelRedeclaration:function(e){return"Label '"+e.labelName+"' is already declared."},LetInLexicalBinding:"'let' is disallowed as a lexically bound name.",LineTerminatorBeforeArrow:"No line break is allowed before '=>'.",MalformedRegExpFlags:"Invalid regular expression flag.",MissingClassName:"A class name is required.",MissingEqInAssignment:"Only '=' operator can be used for specifying default value.",MissingSemicolon:"Missing semicolon.",MissingPlugin:function(e){return"This experimental syntax requires enabling the parser plugin: "+e.missingPlugin.map(function(e){return JSON.stringify(e)}).join(", ")+"."},MissingOneOfPlugins:function(e){return"This experimental syntax requires enabling one of the following parser plugin(s): "+e.missingPlugin.map(function(e){return JSON.stringify(e)}).join(", ")+"."},MissingUnicodeEscape:"Expecting Unicode escape sequence \\uXXXX.",MixingCoalesceWithLogical:"Nullish coalescing operator(??) requires parens when mixing with logical operators.",ModuleAttributeDifferentFromType:"The only accepted module attribute is `type`.",ModuleAttributeInvalidValue:"Only string literals are allowed as module attribute values.",ModuleAttributesWithDuplicateKeys:function(e){return'Duplicate key "'+e.key+'" is not allowed in module attributes.'},ModuleExportNameHasLoneSurrogate:function(e){return"An export name cannot include a lone surrogate, found '\\u"+e.surrogateCharCode.toString(16)+"'."},ModuleExportUndefined:function(e){return"Export '"+e.localName+"' is not defined."},MultipleDefaultsInSwitch:"Multiple default clauses.",NewlineAfterThrow:"Illegal newline after throw.",NoCatchOrFinally:"Missing catch or finally clause.",NumberIdentifier:"Identifier directly after number.",NumericSeparatorInEscapeSequence:"Numeric separators are not allowed inside unicode escape sequences or hex escape sequences.",ObsoleteAwaitStar:"'await*' has been removed from the async functions proposal. Use Promise.all() instead.",OptionalChainingNoNew:"Constructors in/after an Optional Chain are not allowed.",OptionalChainingNoTemplate:"Tagged Template Literals are not allowed in optionalChain.",OverrideOnConstructor:"'override' modifier cannot appear on a constructor declaration.",ParamDupe:"Argument name clash.",PatternHasAccessor:"Object pattern can't contain getter or setter.",PatternHasMethod:"Object pattern can't contain methods.",PrivateInExpectedIn:function(e){var t=e.identifierName;return"Private names are only allowed in property accesses (`obj.#"+t+"`) or in `in` expressions (`#"+t+" in obj`)."},PrivateNameRedeclaration:function(e){return"Duplicate private name #"+e.identifierName+"."},RecordExpressionBarIncorrectEndSyntaxType:"Record expressions ending with '|}' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'.",RecordExpressionBarIncorrectStartSyntaxType:"Record expressions starting with '{|' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'.",RecordExpressionHashIncorrectStartSyntaxType:"Record expressions starting with '#{' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'hash'.",RecordNoProto:"'__proto__' is not allowed in Record expressions.",RestTrailingComma:"Unexpected trailing comma after rest element.",SloppyFunction:"In non-strict mode code, functions can only be declared at top level or inside a block.",SloppyFunctionAnnexB:"In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement.",SourcePhaseImportRequiresDefault:'Only `import source x from "./module"` is valid.',StaticPrototype:"Classes may not have static property named prototype.",SuperNotAllowed:"`super()` is only valid inside a class constructor of a subclass. Maybe a typo in the method name ('constructor') or not extending another class?",SuperPrivateField:"Private fields can't be accessed on super.",TrailingDecorator:"Decorators must be attached to a class element.",TupleExpressionBarIncorrectEndSyntaxType:"Tuple expressions ending with '|]' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'.",TupleExpressionBarIncorrectStartSyntaxType:"Tuple expressions starting with '[|' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'bar'.",TupleExpressionHashIncorrectStartSyntaxType:"Tuple expressions starting with '#[' are only allowed when the 'syntaxType' option of the 'recordAndTuple' plugin is set to 'hash'.",UnexpectedArgumentPlaceholder:"Unexpected argument placeholder.",UnexpectedAwaitAfterPipelineBody:'Unexpected "await" after pipeline body; await must have parentheses in minimal proposal.',UnexpectedDigitAfterHash:"Unexpected digit after hash token.",UnexpectedImportExport:"'import' and 'export' may only appear at the top level.",UnexpectedKeyword:function(e){return"Unexpected keyword '"+e.keyword+"'."},UnexpectedLeadingDecorator:"Leading decorators must be attached to a class declaration.",UnexpectedLexicalDeclaration:"Lexical declaration cannot appear in a single-statement context.",UnexpectedNewTarget:"`new.target` can only be used in functions or class properties.",UnexpectedNumericSeparator:"A numeric separator is only allowed between two digits.",UnexpectedPrivateField:"Unexpected private name.",UnexpectedReservedWord:function(e){return"Unexpected reserved word '"+e.reservedWord+"'."},UnexpectedSuper:"'super' is only allowed in object methods and classes.",UnexpectedToken:function(e){var t=e.expected,r=e.unexpected;return"Unexpected token"+(r?" '"+r+"'.":"")+(t?', expected "'+t+'"':"")},UnexpectedTokenUnaryExponentiation:"Illegal expression. Wrap left hand side or entire exponentiation in parentheses.",UnexpectedUsingDeclaration:"Using declaration cannot appear in the top level when source type is `script` or in the bare case statement.",UnexpectedVoidPattern:"Unexpected void binding.",UnsupportedBind:"Binding should be performed on object property.",UnsupportedDecoratorExport:"A decorated export must export a class declaration.",UnsupportedDefaultExport:"Only expressions, functions or classes are allowed as the `default` export.",UnsupportedImport:"`import` can only be used in `import()` or `import.meta`.",UnsupportedMetaProperty:function(e){var t=e.target;return"The only valid meta property for "+t+" is "+t+"."+e.onlyValidPropertyName+"."},UnsupportedParameterDecorator:"Decorators cannot be used to decorate parameters.",UnsupportedPropertyDecorator:"Decorators cannot be used to decorate object literal properties.",UnsupportedSuper:"'super' can only be used with function calls (i.e. super()) or in property accesses (i.e. super.prop or super[prop]).",UnterminatedComment:"Unterminated comment.",UnterminatedRegExp:"Unterminated regular expression.",UnterminatedString:"Unterminated string constant.",UnterminatedTemplate:"Unterminated template.",UsingDeclarationExport:"Using declaration cannot be exported.",UsingDeclarationHasBindingPattern:"Using declaration cannot have destructuring patterns.",VarRedeclaration:function(e){return"Identifier '"+e.identifierName+"' has already been declared."},VoidPatternCatchClauseParam:"A void binding can not be the catch clause parameter. Use `try { ... } catch { ... }` if you want to discard the caught error.",VoidPatternInitializer:"A void binding may not have an initializer.",YieldBindingIdentifier:"Can not use 'yield' as identifier inside a generator.",YieldInParameter:"Yield expression is not allowed in formal parameters.",YieldNotInGeneratorFunction:"'yield' is only allowed within generator functions.",ZeroDigitNumericSeparator:"Numeric separator can not be used after leading 0."},hh={ParseExpressionEmptyInput:"Unexpected parseExpression() input: The input is empty or contains only comments.",ParseExpressionExpectsEOF:function(e){var t=e.unexpected;return"Unexpected parseExpression() input: The input should contain exactly one expression, but the first expression is followed by the unexpected character `"+String.fromCodePoint(t)+"`."}},bh=new Set(["ArrowFunctionExpression","AssignmentExpression","ConditionalExpression","YieldExpression"]),xh=Object.assign({PipeBodyIsTighter:"Unexpected yield after pipeline body; any yield expression acting as Hack-style pipe body must be parenthesized due to its loose operator precedence.",PipeTopicRequiresHackPipes:'Topic reference is used, but the pipelineOperator plugin was not passed a "proposal": "hack" or "smart" option.',PipeTopicUnbound:"Topic reference is unbound; it must be inside a pipe body.",PipeTopicUnconfiguredToken:function(e){var t=e.token;return"Invalid topic token "+t+". In order to use "+t+' as a topic reference, the pipelineOperator plugin must be configured with { "proposal": "hack", "topicToken": "'+t+'" }.'},PipeTopicUnused:"Hack-style pipe body does not contain a topic reference; Hack-style pipes must use topic at least once.",PipeUnparenthesizedBody:function(e){var t=e.type;return"Hack-style pipe body cannot be an unparenthesized "+yh({type:t})+"; please wrap it in parentheses."}},{PipelineBodyNoArrow:'Unexpected arrow "=>" after pipeline body; arrow function in pipeline body must be parenthesized.',PipelineBodySequenceExpression:"Pipeline body may not be a comma-separated sequence expression.",PipelineHeadSequenceExpression:"Pipeline head should not be a comma-separated sequence expression.",PipelineTopicUnused:"Pipeline is in topic style but does not use topic reference.",PrimaryTopicNotAllowed:"Topic reference was used in a lexical context without topic binding.",PrimaryTopicRequiresSmartPipeline:'Topic reference is used, but the pipelineOperator plugin was not passed a "proposal": "hack" or "smart" option.'}),vh=["message"];function Rh(e,t,r){Object.defineProperty(e,t,{enumerable:!1,configurable:!0,value:r})}function jh(e,t){if(Array.isArray(e))return function(t){return jh(t,e[0])};for(var r={},a=function(){var a=s[n],o=e[a],i="string"==typeof o?{message:function(){return o}}:"function"==typeof o?{message:o}:o,d=i.message,c=u(i,vh),l="string"==typeof d?function(){return d}:d;r[a]=function(e){var t=e.toMessage,r=e.code,a=e.reasonCode,n=e.syntaxPlugin,s="MissingPlugin"===a||"MissingOneOfPlugins"===a,o={AccessorCannotDeclareThisParameter:"AccesorCannotDeclareThisParameter",AccessorCannotHaveTypeParameters:"AccesorCannotHaveTypeParameters",ConstInitializerMustBeStringOrNumericLiteralOrLiteralEnumReference:"ConstInitiailizerMustBeStringOrNumericLiteralOrLiteralEnumReference",SetAccessorCannotHaveOptionalParameter:"SetAccesorCannotHaveOptionalParameter",SetAccessorCannotHaveRestParameter:"SetAccesorCannotHaveRestParameter",SetAccessorCannotHaveReturnType:"SetAccesorCannotHaveReturnType"};return o[a]&&(a=o[a]),function e(o,i){var d=new SyntaxError;return d.code=r,d.reasonCode=a,d.loc=o,d.pos=o.index,d.syntaxPlugin=n,s&&(d.missingPlugin=i.missingPlugin),Rh(d,"clone",function(t){var r;void 0===t&&(t={});var a=null!=(r=t.loc)?r:o,n=a.line,s=a.column,d=a.index;return e(new dh(n,s,d),Object.assign({},i,t.details))}),Rh(d,"details",i),Object.defineProperty(d,"message",{configurable:!0,get:function(){var e=t(i)+" ("+o.line+":"+o.column+")";return this.message=e,e},set:function(e){Object.defineProperty(this,"message",{value:e,writable:!0})}}),d}}(Object.assign({code:"BABEL_PARSER_SYNTAX_ERROR",reasonCode:a,toMessage:l},t?{syntaxPlugin:t}:{},c))},n=0,s=Object.keys(e);n...",!0)};Gh.template=new qh("`",!0);var Wh=!0,Vh=!0,Hh=!0,Kh=!0,zh=!0,Xh=o(function(e,t){void 0===t&&(t={}),this.label=void 0,this.keyword=void 0,this.beforeExpr=void 0,this.startsExpr=void 0,this.rightAssociative=void 0,this.isLoop=void 0,this.isAssign=void 0,this.prefix=void 0,this.postfix=void 0,this.binop=void 0,this.label=e,this.keyword=t.keyword,this.beforeExpr=!!t.beforeExpr,this.startsExpr=!!t.startsExpr,this.rightAssociative=!!t.rightAssociative,this.isLoop=!!t.isLoop,this.isAssign=!!t.isAssign,this.prefix=!!t.prefix,this.postfix=!!t.postfix,this.binop=null!=t.binop?t.binop:null,this.updateContext=null}),Jh=new Map;function Yh(e,t){void 0===t&&(t={}),t.keyword=e;var r=sb(e,t);return Jh.set(e,r),r}function $h(e,t){return sb(e,{beforeExpr:Wh,binop:t})}var Qh=-1,Zh=[],eb=[],tb=[],rb=[],ab=[],nb=[];function sb(e,t){var r,a,n,s;return void 0===t&&(t={}),++Qh,eb.push(e),tb.push(null!=(r=t.binop)?r:-1),rb.push(null!=(a=t.beforeExpr)&&a),ab.push(null!=(n=t.startsExpr)&&n),nb.push(null!=(s=t.prefix)&&s),Zh.push(new Xh(e,t)),Qh}function ob(e,t){var r,a,n,s;return void 0===t&&(t={}),++Qh,Jh.set(e,Qh),eb.push(e),tb.push(null!=(r=t.binop)?r:-1),rb.push(null!=(a=t.beforeExpr)&&a),ab.push(null!=(n=t.startsExpr)&&n),nb.push(null!=(s=t.prefix)&&s),Zh.push(new Xh("name",t)),Qh}var ib={bracketL:sb("[",{beforeExpr:Wh,startsExpr:Vh}),bracketHashL:sb("#[",{beforeExpr:Wh,startsExpr:Vh}),bracketBarL:sb("[|",{beforeExpr:Wh,startsExpr:Vh}),bracketR:sb("]"),bracketBarR:sb("|]"),braceL:sb("{",{beforeExpr:Wh,startsExpr:Vh}),braceBarL:sb("{|",{beforeExpr:Wh,startsExpr:Vh}),braceHashL:sb("#{",{beforeExpr:Wh,startsExpr:Vh}),braceR:sb("}"),braceBarR:sb("|}"),parenL:sb("(",{beforeExpr:Wh,startsExpr:Vh}),parenR:sb(")"),comma:sb(",",{beforeExpr:Wh}),semi:sb(";",{beforeExpr:Wh}),colon:sb(":",{beforeExpr:Wh}),doubleColon:sb("::",{beforeExpr:Wh}),dot:sb("."),question:sb("?",{beforeExpr:Wh}),questionDot:sb("?."),arrow:sb("=>",{beforeExpr:Wh}),template:sb("template"),ellipsis:sb("...",{beforeExpr:Wh}),backQuote:sb("`",{startsExpr:Vh}),dollarBraceL:sb("${",{beforeExpr:Wh,startsExpr:Vh}),templateTail:sb("...`",{startsExpr:Vh}),templateNonTail:sb("...${",{beforeExpr:Wh,startsExpr:Vh}),at:sb("@"),hash:sb("#",{startsExpr:Vh}),interpreterDirective:sb("#!..."),eq:sb("=",{beforeExpr:Wh,isAssign:Kh}),assign:sb("_=",{beforeExpr:Wh,isAssign:Kh}),slashAssign:sb("_=",{beforeExpr:Wh,isAssign:Kh}),xorAssign:sb("_=",{beforeExpr:Wh,isAssign:Kh}),moduloAssign:sb("_=",{beforeExpr:Wh,isAssign:Kh}),incDec:sb("++/--",{prefix:zh,postfix:!0,startsExpr:Vh}),bang:sb("!",{beforeExpr:Wh,prefix:zh,startsExpr:Vh}),tilde:sb("~",{beforeExpr:Wh,prefix:zh,startsExpr:Vh}),doubleCaret:sb("^^",{startsExpr:Vh}),doubleAt:sb("@@",{startsExpr:Vh}),pipeline:$h("|>",0),nullishCoalescing:$h("??",1),logicalOR:$h("||",1),logicalAND:$h("&&",2),bitwiseOR:$h("|",3),bitwiseXOR:$h("^",4),bitwiseAND:$h("&",5),equality:$h("==/!=/===/!==",6),lt:$h("/<=/>=",7),gt:$h("/<=/>=",7),relational:$h("/<=/>=",7),bitShift:$h("<>/>>>",8),bitShiftL:$h("<>/>>>",8),bitShiftR:$h("<>/>>>",8),plusMin:sb("+/-",{beforeExpr:Wh,binop:9,prefix:zh,startsExpr:Vh}),modulo:sb("%",{binop:10,startsExpr:Vh}),star:sb("*",{binop:10}),slash:$h("/",10),exponent:sb("**",{beforeExpr:Wh,binop:11,rightAssociative:!0}),_in:Yh("in",{beforeExpr:Wh,binop:7}),_instanceof:Yh("instanceof",{beforeExpr:Wh,binop:7}),_break:Yh("break"),_case:Yh("case",{beforeExpr:Wh}),_catch:Yh("catch"),_continue:Yh("continue"),_debugger:Yh("debugger"),_default:Yh("default",{beforeExpr:Wh}),_else:Yh("else",{beforeExpr:Wh}),_finally:Yh("finally"),_function:Yh("function",{startsExpr:Vh}),_if:Yh("if"),_return:Yh("return",{beforeExpr:Wh}),_switch:Yh("switch"),_throw:Yh("throw",{beforeExpr:Wh,prefix:zh,startsExpr:Vh}),_try:Yh("try"),_var:Yh("var"),_const:Yh("const"),_with:Yh("with"),_new:Yh("new",{beforeExpr:Wh,startsExpr:Vh}),_this:Yh("this",{startsExpr:Vh}),_super:Yh("super",{startsExpr:Vh}),_class:Yh("class",{startsExpr:Vh}),_extends:Yh("extends",{beforeExpr:Wh}),_export:Yh("export"),_import:Yh("import",{startsExpr:Vh}),_null:Yh("null",{startsExpr:Vh}),_true:Yh("true",{startsExpr:Vh}),_false:Yh("false",{startsExpr:Vh}),_typeof:Yh("typeof",{beforeExpr:Wh,prefix:zh,startsExpr:Vh}),_void:Yh("void",{beforeExpr:Wh,prefix:zh,startsExpr:Vh}),_delete:Yh("delete",{beforeExpr:Wh,prefix:zh,startsExpr:Vh}),_do:Yh("do",{isLoop:Hh,beforeExpr:Wh}),_for:Yh("for",{isLoop:Hh}),_while:Yh("while",{isLoop:Hh}),_as:ob("as",{startsExpr:Vh}),_assert:ob("assert",{startsExpr:Vh}),_async:ob("async",{startsExpr:Vh}),_await:ob("await",{startsExpr:Vh}),_defer:ob("defer",{startsExpr:Vh}),_from:ob("from",{startsExpr:Vh}),_get:ob("get",{startsExpr:Vh}),_let:ob("let",{startsExpr:Vh}),_meta:ob("meta",{startsExpr:Vh}),_of:ob("of",{startsExpr:Vh}),_sent:ob("sent",{startsExpr:Vh}),_set:ob("set",{startsExpr:Vh}),_source:ob("source",{startsExpr:Vh}),_static:ob("static",{startsExpr:Vh}),_using:ob("using",{startsExpr:Vh}),_yield:ob("yield",{startsExpr:Vh}),_asserts:ob("asserts",{startsExpr:Vh}),_checks:ob("checks",{startsExpr:Vh}),_exports:ob("exports",{startsExpr:Vh}),_global:ob("global",{startsExpr:Vh}),_implements:ob("implements",{startsExpr:Vh}),_intrinsic:ob("intrinsic",{startsExpr:Vh}),_infer:ob("infer",{startsExpr:Vh}),_is:ob("is",{startsExpr:Vh}),_mixins:ob("mixins",{startsExpr:Vh}),_proto:ob("proto",{startsExpr:Vh}),_require:ob("require",{startsExpr:Vh}),_satisfies:ob("satisfies",{startsExpr:Vh}),_keyof:ob("keyof",{startsExpr:Vh}),_readonly:ob("readonly",{startsExpr:Vh}),_unique:ob("unique",{startsExpr:Vh}),_abstract:ob("abstract",{startsExpr:Vh}),_declare:ob("declare",{startsExpr:Vh}),_enum:ob("enum",{startsExpr:Vh}),_module:ob("module",{startsExpr:Vh}),_namespace:ob("namespace",{startsExpr:Vh}),_interface:ob("interface",{startsExpr:Vh}),_type:ob("type",{startsExpr:Vh}),_opaque:ob("opaque",{startsExpr:Vh}),name:sb("name",{startsExpr:Vh}),placeholder:sb("%%",{startsExpr:Vh}),string:sb("string",{startsExpr:Vh}),num:sb("num",{startsExpr:Vh}),bigint:sb("bigint",{startsExpr:Vh}),decimal:sb("decimal",{startsExpr:Vh}),regexp:sb("regexp",{startsExpr:Vh}),privateName:sb("#name",{startsExpr:Vh}),eof:sb("eof"),jsxName:sb("jsxName"),jsxText:sb("jsxText",{beforeExpr:Wh}),jsxTagStart:sb("jsxTagStart",{startsExpr:Vh}),jsxTagEnd:sb("jsxTagEnd")};function db(e){return e>=93&&e<=133}function cb(e){return e>=58&&e<=133}function lb(e){return e>=58&&e<=137}function ub(e){return ab[e]}function pb(e){return e>=129&&e<=131}function fb(e){return e>=58&&e<=92}function gb(e){return 34===e}function yb(e){return eb[e]}function mb(e){return tb[e]}function hb(e){return e>=24&&e<=25}function bb(e){return Zh[e]}Zh[8].updateContext=function(e){e.pop()},Zh[5].updateContext=Zh[7].updateContext=Zh[23].updateContext=function(e){e.push(Gh.brace)},Zh[22].updateContext=function(e){e[e.length-1]===Gh.template?e.pop():e.push(Gh.template)},Zh[143].updateContext=function(e){e.push(Gh.j_expr,Gh.j_oTag)};var xb=new Set(["break","case","catch","continue","debugger","default","do","else","finally","for","function","if","return","switch","throw","try","var","const","while","with","new","this","super","class","extends","export","import","null","true","false","in","instanceof","typeof","void","delete","implements","interface","let","package","private","protected","public","static","yield","eval","arguments","enum","await"]);var vb,Rb=0,jb=1,wb=2,Eb=4,Sb=8,Tb=16,Pb=32,Ab=64,kb=128,Cb=256,_b=512,Ib=1024,Db=514,Nb=576,Ob=1667,Bb=1,Mb=2,Fb=4,Lb=8,Ub=16,qb=128,Gb=256,Wb=512,Vb=1024,Hb=2048,Kb=4096,zb=8192,Xb=8331,Jb=8201,Yb=9,$b=5,Qb=17,Zb=130,ex=2,tx=8459,rx=1024,ax=64,nx=65,sx=8971,ox=1024,ix=4098,dx=4096,cx=2048,lx=0,ux=4,px=3,fx=6,gx=5,yx=2,mx=1,hx=1,bx=2,xx=4,vx=o(function(e){this.flags=0,this.names=new Map,this.firstLexicalName="",this.flags=e}),Rx=function(){function e(e,t){this.parser=void 0,this.scopeStack=[],this.inModule=void 0,this.undefinedExports=new Map,this.parser=e,this.inModule=t}var t=e.prototype;return t.createScope=function(e){return new vx(e)},t.enter=function(e){this.scopeStack.push(this.createScope(e))},t.exit=function(){return this.scopeStack.pop().flags},t.treatFunctionsAsVarInScope=function(e){return!!(e.flags&(wb|kb)||!this.parser.inModule&&e.flags&jb)},t.declareName=function(e,t,r){var a=this.currentScope();if(t&Lb||t&Ub){this.checkRedeclarationInScope(a,e,t,r);var n=a.names.get(e)||0;t&Ub?n|=xx:(a.firstLexicalName||(a.firstLexicalName=e),n|=bx),a.names.set(e,n),t&Lb&&this.maybeExportDefined(a,e)}else if(t&Fb)for(var s=this.scopeStack.length-1;s>=0&&(a=this.scopeStack[s],this.checkRedeclarationInScope(a,e,t,r),a.names.set(e,(a.names.get(e)||0)|hx),this.maybeExportDefined(a,e),!(a.flags&Ob));--s);this.parser.inModule&&a.flags&jb&&this.undefinedExports.delete(e)},t.maybeExportDefined=function(e,t){this.parser.inModule&&e.flags&jb&&this.undefinedExports.delete(t)},t.checkRedeclarationInScope=function(e,t,r,a){this.isRedeclaredInScope(e,t,r)&&this.parser.raise(wh.VarRedeclaration,a,{identifierName:t})},t.isRedeclaredInScope=function(e,t,r){if(!(r&Bb))return!1;if(r&Lb)return e.names.has(t);var a=e.names.get(t);return r&Ub?(a&bx)>0||!this.treatFunctionsAsVarInScope(e)&&(a&hx)>0:(a&bx)>0&&!(e.flags&Sb&&e.firstLexicalName===t)||!this.treatFunctionsAsVarInScope(e)&&(a&xx)>0},t.checkLocalExport=function(e){var t=e.name;this.scopeStack[0].names.has(t)||this.undefinedExports.set(t,e.loc.start)},t.currentScope=function(){return this.scopeStack[this.scopeStack.length-1]},t.currentVarScopeFlags=function(){for(var e=this.scopeStack.length-1;;e--){var t=this.scopeStack[e].flags;if(t&Ob)return t}},t.currentThisScopeFlags=function(){for(var e=this.scopeStack.length-1;;e--){var t=this.scopeStack[e].flags;if(t&(Ob|Ab)&&!(t&Eb))return t}},o(e,[{key:"inTopLevel",get:function(){return(this.currentScope().flags&jb)>0}},{key:"inFunction",get:function(){return(this.currentVarScopeFlags()&wb)>0}},{key:"allowSuper",get:function(){return(this.currentThisScopeFlags()&Tb)>0}},{key:"allowDirectSuper",get:function(){return(this.currentThisScopeFlags()&Pb)>0}},{key:"allowNewTarget",get:function(){return(this.currentThisScopeFlags()&_b)>0}},{key:"inClass",get:function(){return(this.currentThisScopeFlags()&Ab)>0}},{key:"inClassAndNotInNonArrowFunction",get:function(){var e=this.currentThisScopeFlags();return(e&Ab)>0&&0===(e&wb)}},{key:"inStaticBlock",get:function(){for(var e=this.scopeStack.length-1;;e--){var t=this.scopeStack[e].flags;if(t&kb)return!0;if(t&(Ob|Ab))return!1}}},{key:"inNonArrowFunction",get:function(){return(this.currentThisScopeFlags()&wb)>0}},{key:"inBareCaseStatement",get:function(){return(this.currentScope().flags&Cb)>0}},{key:"treatFunctionsAsVar",get:function(){return this.treatFunctionsAsVarInScope(this.currentScope())}}])}(),jx=function(e){function t(){for(var t,r=arguments.length,a=new Array(r),n=0;n0||(n&bx)>0}return!1},r.checkLocalExport=function(t){this.scopeStack[0].declareFunctions.has(t.name)||e.prototype.checkLocalExport.call(this,t)},o(t)}(Rx),Ex=new Set(["_","any","bool","boolean","empty","extends","false","interface","mixed","null","number","static","string","true","typeof","void"]),Sx=jh(vb||(vb=h(["flow"])))({AmbiguousConditionalArrow:"Ambiguous expression: wrap the arrow functions in parentheses to disambiguate.",AmbiguousDeclareModuleKind:"Found both `declare module.exports` and `declare export` in the same module. Modules can only have 1 since they are either an ES module or they are a CommonJS module.",AssignReservedType:function(e){return"Cannot overwrite reserved type "+e.reservedType+"."},DeclareClassElement:"The `declare` modifier can only appear on class fields.",DeclareClassFieldInitializer:"Initializers are not allowed in fields with the `declare` modifier.",DuplicateDeclareModuleExports:"Duplicate `declare module.exports` statement.",EnumBooleanMemberNotInitialized:function(e){var t=e.memberName;return"Boolean enum members need to be initialized. Use either `"+t+" = true,` or `"+t+" = false,` in enum `"+e.enumName+"`."},EnumDuplicateMemberName:function(e){return"Enum member names need to be unique, but the name `"+e.memberName+"` has already been used before in enum `"+e.enumName+"`."},EnumInconsistentMemberValues:function(e){return"Enum `"+e.enumName+"` has inconsistent member initializers. Either use no initializers, or consistently use literals (either booleans, numbers, or strings) for all member initializers."},EnumInvalidExplicitType:function(e){return"Enum type `"+e.invalidEnumType+"` is not valid. Use one of `boolean`, `number`, `string`, or `symbol` in enum `"+e.enumName+"`."},EnumInvalidExplicitTypeUnknownSupplied:function(e){return"Supplied enum type is not valid. Use one of `boolean`, `number`, `string`, or `symbol` in enum `"+e.enumName+"`."},EnumInvalidMemberInitializerPrimaryType:function(e){var t=e.enumName,r=e.memberName,a=e.explicitType;return"Enum `"+t+"` has type `"+a+"`, so the initializer of `"+r+"` needs to be a "+a+" literal."},EnumInvalidMemberInitializerSymbolType:function(e){var t=e.enumName;return"Symbol enum members cannot be initialized. Use `"+e.memberName+",` in enum `"+t+"`."},EnumInvalidMemberInitializerUnknownType:function(e){var t=e.enumName;return"The enum member initializer for `"+e.memberName+"` needs to be a literal (either a boolean, number, or string) in enum `"+t+"`."},EnumInvalidMemberName:function(e){var t=e.enumName;return"Enum member names cannot start with lowercase 'a' through 'z'. Instead of using `"+e.memberName+"`, consider using `"+e.suggestion+"`, in enum `"+t+"`."},EnumNumberMemberNotInitialized:function(e){var t=e.enumName;return"Number enum members need to be initialized, e.g. `"+e.memberName+" = 1` in enum `"+t+"`."},EnumStringMemberInconsistentlyInitialized:function(e){return"String enum members need to consistently either all use initializers, or use no initializers, in enum `"+e.enumName+"`."},GetterMayNotHaveThisParam:"A getter cannot have a `this` parameter.",ImportReflectionHasImportType:"An `import module` declaration can not use `type` or `typeof` keyword.",ImportTypeShorthandOnlyInPureImport:"The `type` and `typeof` keywords on named imports can only be used on regular `import` statements. It cannot be used with `import type` or `import typeof` statements.",InexactInsideExact:"Explicit inexact syntax cannot appear inside an explicit exact object type.",InexactInsideNonObject:"Explicit inexact syntax cannot appear in class or interface definitions.",InexactVariance:"Explicit inexact syntax cannot have variance.",InvalidNonTypeImportInDeclareModule:"Imports within a `declare module` body must always be `import type` or `import typeof`.",MissingTypeParamDefault:"Type parameter declaration needs a default, since a preceding type parameter declaration has a default.",NestedDeclareModule:"`declare module` cannot be used inside another `declare module`.",NestedFlowComment:"Cannot have a flow comment inside another flow comment.",PatternIsOptional:Object.assign({message:"A binding pattern parameter cannot be optional in an implementation signature."},{reasonCode:"OptionalBindingPattern"}),SetterMayNotHaveThisParam:"A setter cannot have a `this` parameter.",SpreadVariance:"Spread properties cannot have variance.",ThisParamAnnotationRequired:"A type annotation is required for the `this` parameter.",ThisParamBannedInConstructor:"Constructors cannot have a `this` parameter; constructors don't bind `this` like other functions.",ThisParamMayNotBeOptional:"The `this` parameter cannot be optional.",ThisParamMustBeFirst:"The `this` parameter must be the first function parameter.",ThisParamNoDefault:"The `this` parameter may not have a default value.",TypeBeforeInitializer:"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`.",TypeCastInPattern:"The type cast expression is expected to be wrapped with parenthesis.",UnexpectedExplicitInexactInObject:"Explicit inexact syntax must appear at the end of an inexact object.",UnexpectedReservedType:function(e){return"Unexpected reserved type "+e.reservedType+"."},UnexpectedReservedUnderscore:"`_` is only allowed as a type argument to call or new.",UnexpectedSpaceBetweenModuloChecks:"Spaces between `%` and `checks` are not allowed here.",UnexpectedSpreadType:"Spread operator cannot appear in class or interface definitions.",UnexpectedSubtractionOperand:'Unexpected token, expected "number" or "bigint".',UnexpectedTokenAfterTypeParameter:"Expected an arrow function after this type parameter declaration.",UnexpectedTypeParameterBeforeAsyncArrowFunction:"Type parameters must come after the async keyword, e.g. instead of ` async () => {}`, use `async () => {}`.",UnsupportedDeclareExportKind:function(e){return"`declare export "+e.unsupportedExportKind+"` is not supported. Use `"+e.suggestion+"` instead."},UnsupportedStatementInDeclareModule:"Only declares and type imports are allowed inside declare module.",UnterminatedFlowComment:"Unterminated flow-comment."});function Tx(e){return"type"===e.importKind||"typeof"===e.importKind}var Px={const:"declare export var",let:"declare export var",type:"export type",interface:"export interface"};var Ax=/\*?\s*@((?:no)?flow)\b/,kx={__proto__:null,quot:'"',amp:"&",apos:"'",lt:"<",gt:">",nbsp:"\xa0",iexcl:"\xa1",cent:"\xa2",pound:"\xa3",curren:"\xa4",yen:"\xa5",brvbar:"\xa6",sect:"\xa7",uml:"\xa8",copy:"\xa9",ordf:"\xaa",laquo:"\xab",not:"\xac",shy:"\xad",reg:"\xae",macr:"\xaf",deg:"\xb0",plusmn:"\xb1",sup2:"\xb2",sup3:"\xb3",acute:"\xb4",micro:"\xb5",para:"\xb6",middot:"\xb7",cedil:"\xb8",sup1:"\xb9",ordm:"\xba",raquo:"\xbb",frac14:"\xbc",frac12:"\xbd",frac34:"\xbe",iquest:"\xbf",Agrave:"\xc0",Aacute:"\xc1",Acirc:"\xc2",Atilde:"\xc3",Auml:"\xc4",Aring:"\xc5",AElig:"\xc6",Ccedil:"\xc7",Egrave:"\xc8",Eacute:"\xc9",Ecirc:"\xca",Euml:"\xcb",Igrave:"\xcc",Iacute:"\xcd",Icirc:"\xce",Iuml:"\xcf",ETH:"\xd0",Ntilde:"\xd1",Ograve:"\xd2",Oacute:"\xd3",Ocirc:"\xd4",Otilde:"\xd5",Ouml:"\xd6",times:"\xd7",Oslash:"\xd8",Ugrave:"\xd9",Uacute:"\xda",Ucirc:"\xdb",Uuml:"\xdc",Yacute:"\xdd",THORN:"\xde",szlig:"\xdf",agrave:"\xe0",aacute:"\xe1",acirc:"\xe2",atilde:"\xe3",auml:"\xe4",aring:"\xe5",aelig:"\xe6",ccedil:"\xe7",egrave:"\xe8",eacute:"\xe9",ecirc:"\xea",euml:"\xeb",igrave:"\xec",iacute:"\xed",icirc:"\xee",iuml:"\xef",eth:"\xf0",ntilde:"\xf1",ograve:"\xf2",oacute:"\xf3",ocirc:"\xf4",otilde:"\xf5",ouml:"\xf6",divide:"\xf7",oslash:"\xf8",ugrave:"\xf9",uacute:"\xfa",ucirc:"\xfb",uuml:"\xfc",yacute:"\xfd",thorn:"\xfe",yuml:"\xff",OElig:"\u0152",oelig:"\u0153",Scaron:"\u0160",scaron:"\u0161",Yuml:"\u0178",fnof:"\u0192",circ:"\u02c6",tilde:"\u02dc",Alpha:"\u0391",Beta:"\u0392",Gamma:"\u0393",Delta:"\u0394",Epsilon:"\u0395",Zeta:"\u0396",Eta:"\u0397",Theta:"\u0398",Iota:"\u0399",Kappa:"\u039a",Lambda:"\u039b",Mu:"\u039c",Nu:"\u039d",Xi:"\u039e",Omicron:"\u039f",Pi:"\u03a0",Rho:"\u03a1",Sigma:"\u03a3",Tau:"\u03a4",Upsilon:"\u03a5",Phi:"\u03a6",Chi:"\u03a7",Psi:"\u03a8",Omega:"\u03a9",alpha:"\u03b1",beta:"\u03b2",gamma:"\u03b3",delta:"\u03b4",epsilon:"\u03b5",zeta:"\u03b6",eta:"\u03b7",theta:"\u03b8",iota:"\u03b9",kappa:"\u03ba",lambda:"\u03bb",mu:"\u03bc",nu:"\u03bd",xi:"\u03be",omicron:"\u03bf",pi:"\u03c0",rho:"\u03c1",sigmaf:"\u03c2",sigma:"\u03c3",tau:"\u03c4",upsilon:"\u03c5",phi:"\u03c6",chi:"\u03c7",psi:"\u03c8",omega:"\u03c9",thetasym:"\u03d1",upsih:"\u03d2",piv:"\u03d6",ensp:"\u2002",emsp:"\u2003",thinsp:"\u2009",zwnj:"\u200c",zwj:"\u200d",lrm:"\u200e",rlm:"\u200f",ndash:"\u2013",mdash:"\u2014",lsquo:"\u2018",rsquo:"\u2019",sbquo:"\u201a",ldquo:"\u201c",rdquo:"\u201d",bdquo:"\u201e",dagger:"\u2020",Dagger:"\u2021",bull:"\u2022",hellip:"\u2026",permil:"\u2030",prime:"\u2032",Prime:"\u2033",lsaquo:"\u2039",rsaquo:"\u203a",oline:"\u203e",frasl:"\u2044",euro:"\u20ac",image:"\u2111",weierp:"\u2118",real:"\u211c",trade:"\u2122",alefsym:"\u2135",larr:"\u2190",uarr:"\u2191",rarr:"\u2192",darr:"\u2193",harr:"\u2194",crarr:"\u21b5",lArr:"\u21d0",uArr:"\u21d1",rArr:"\u21d2",dArr:"\u21d3",hArr:"\u21d4",forall:"\u2200",part:"\u2202",exist:"\u2203",empty:"\u2205",nabla:"\u2207",isin:"\u2208",notin:"\u2209",ni:"\u220b",prod:"\u220f",sum:"\u2211",minus:"\u2212",lowast:"\u2217",radic:"\u221a",prop:"\u221d",infin:"\u221e",ang:"\u2220",and:"\u2227",or:"\u2228",cap:"\u2229",cup:"\u222a",int:"\u222b",there4:"\u2234",sim:"\u223c",cong:"\u2245",asymp:"\u2248",ne:"\u2260",equiv:"\u2261",le:"\u2264",ge:"\u2265",sub:"\u2282",sup:"\u2283",nsub:"\u2284",sube:"\u2286",supe:"\u2287",oplus:"\u2295",otimes:"\u2297",perp:"\u22a5",sdot:"\u22c5",lceil:"\u2308",rceil:"\u2309",lfloor:"\u230a",rfloor:"\u230b",lang:"\u2329",rang:"\u232a",loz:"\u25ca",spades:"\u2660",clubs:"\u2663",hearts:"\u2665",diams:"\u2666"},Cx=new RegExp(/\r\n|[\r\n\u2028\u2029]/.source,"g");function _x(e){switch(e){case 10:case 13:case 8232:case 8233:return!0;default:return!1}}function Ix(e,t,r){for(var a=t;a."},MissingClosingTagFragment:"Expected corresponding JSX closing tag for <>.",UnexpectedSequenceExpression:"Sequence expressions cannot be directly nested inside JSX. Did you mean to wrap it in parentheses (...)?",UnexpectedToken:function(e){var t=e.unexpected;return"Unexpected token `"+t+"`. Did you mean `"+e.HTMLEntity+"` or `{'"+t+"'}`?"},UnsupportedJsxValue:"JSX value should be either an expression or a quoted JSX text.",UnterminatedJsxContent:"Unterminated JSX contents.",UnwrappedAdjacentJSXElements:"Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...?"});function Fx(e){return!!e&&("JSXOpeningFragment"===e.type||"JSXClosingFragment"===e.type)}function Lx(e){if("JSXIdentifier"===e.type)return e.name;if("JSXNamespacedName"===e.type)return e.namespace.name+":"+e.name.name;if("JSXMemberExpression"===e.type)return Lx(e.object)+"."+Lx(e.property);throw new Error("Node had unexpected type: "+e.type)}var Ux=function(e){function t(){for(var t,r=arguments.length,a=new Array(r),n=0;n1)for(var a=0;a0?!(a&Gb)||!!(a&Wb)!==(4&n)>0:a&qb&&(8&n)>0?!!(t.names.get(r)&bx)&&!!(a&Bb):!!(a&Mb&&(1&n)>0)||e.prototype.isRedeclaredInScope.call(this,t,r,a)},r.checkLocalExport=function(t){var r=t.name;if(!this.hasImport(r)){for(var a=this.scopeStack.length-1;a>=0;a--){var n=this.scopeStack[a].tsNames.get(r);if((1&n)>0||(16&n)>0)return}e.prototype.checkLocalExport.call(this,t)}},o(t)}(Rx),Gx=0,Wx=1,Vx=2,Hx=4,Kx=8,zx=function(){function e(){this.stacks=[]}var t=e.prototype;return t.enter=function(e){this.stacks.push(e)},t.exit=function(){this.stacks.pop()},t.currentFlags=function(){return this.stacks[this.stacks.length-1]},o(e,[{key:"hasAwait",get:function(){return(this.currentFlags()&Vx)>0}},{key:"hasYield",get:function(){return(this.currentFlags()&Wx)>0}},{key:"hasReturn",get:function(){return(this.currentFlags()&Hx)>0}},{key:"hasIn",get:function(){return(this.currentFlags()&Kx)>0}}])}();function Xx(e,t){return(e?Vx:0)|(t?Wx:0)}var Jx=function(){function e(){this.sawUnambiguousESM=!1,this.ambiguousScriptDifferentAst=!1}var t=e.prototype;return t.sourceToOffsetPos=function(e){return e+this.startIndex},t.offsetToSourcePos=function(e){return e-this.startIndex},t.hasPlugin=function(e){if("string"==typeof e)return this.plugins.has(e);var t=e[0],r=e[1];if(!this.hasPlugin(t))return!1;for(var a=this.plugins.get(t),n=0,s=Object.keys(r);n0;)a=t[--n];null===a||a.start>r.start?$x(e,r.comments):Yx(a,r.comments)}var Zx=function(e){function t(){return e.apply(this,arguments)||this}c(t,e);var r=t.prototype;return r.addComment=function(e){this.filename&&(e.loc.filename=this.filename);var t=this.state.commentsLen;this.comments.length!==t&&(this.comments.length=t),this.comments.push(e),this.state.commentsLen++},r.processComment=function(e){var t=this.state.commentStack,r=t.length;if(0!==r){var a=r-1,n=t[a];n.start===e.end&&(n.leadingNode=e,a--);for(var s=e.start;a>=0;a--){var o=t[a],i=o.end;if(!(i>s)){i===s&&(o.trailingNode=e);break}o.containingNode=e,this.finalizeComment(o),t.splice(a,1)}}},r.finalizeComment=function(e){var t,r=e.comments;if(null!==e.leadingNode||null!==e.trailingNode)null!==e.leadingNode&&Yx(e.leadingNode,r),null!==e.trailingNode&&function(e,t){var r;void 0===e.leadingComments?e.leadingComments=t:(r=e.leadingComments).unshift.apply(r,t)}(e.trailingNode,r);else{var a=e.containingNode,n=e.start;if(44===this.input.charCodeAt(this.offsetToSourcePos(n)-1))switch(a.type){case"ObjectExpression":case"ObjectPattern":case"RecordExpression":Qx(a,a.properties,e);break;case"CallExpression":case"OptionalCallExpression":Qx(a,a.arguments,e);break;case"ImportExpression":Qx(a,[a.source,null!=(t=a.options)?t:null],e);break;case"FunctionDeclaration":case"FunctionExpression":case"ArrowFunctionExpression":case"ObjectMethod":case"ClassMethod":case"ClassPrivateMethod":Qx(a,a.params,e);break;case"ArrayExpression":case"ArrayPattern":case"TupleExpression":Qx(a,a.elements,e);break;case"ExportNamedDeclaration":case"ImportDeclaration":Qx(a,a.specifiers,e);break;case"TSEnumDeclaration":case"TSEnumBody":Qx(a,a.members,e);break;default:$x(a,r)}else $x(a,r)}},r.finalizeRemainingComments=function(){for(var e=this.state.commentStack,t=e.length-1;t>=0;t--)this.finalizeComment(e[t]);this.state.commentStack=[]},r.resetPreviousNodeTrailingComments=function(e){var t=this.state.commentStack,r=t.length;if(0!==r){var a=t[r-1];a.leadingNode===e&&(a.leadingNode=null)}},r.takeSurroundingComments=function(e,t,r){var a=this.state.commentStack,n=a.length;if(0!==n)for(var s=n-1;s>=0;s--){var o=a[s],i=o.end;if(o.start===r)o.leadingNode=e;else if(i===t)o.trailingNode=e;else if(i0},set:function(e){e?this.flags|=1:this.flags&=-2}},{key:"maybeInArrowParameters",get:function(){return(2&this.flags)>0},set:function(e){e?this.flags|=2:this.flags&=-3}},{key:"inType",get:function(){return(4&this.flags)>0},set:function(e){e?this.flags|=4:this.flags&=-5}},{key:"noAnonFunctionType",get:function(){return(8&this.flags)>0},set:function(e){e?this.flags|=8:this.flags&=-9}},{key:"hasFlowComment",get:function(){return(16&this.flags)>0},set:function(e){e?this.flags|=16:this.flags&=-17}},{key:"isAmbientContext",get:function(){return(32&this.flags)>0},set:function(e){e?this.flags|=32:this.flags&=-33}},{key:"inAbstractClass",get:function(){return(64&this.flags)>0},set:function(e){e?this.flags|=64:this.flags&=-65}},{key:"inDisallowConditionalTypesContext",get:function(){return(128&this.flags)>0},set:function(e){e?this.flags|=128:this.flags&=-129}},{key:"soloAwait",get:function(){return(256&this.flags)>0},set:function(e){e?this.flags|=256:this.flags&=-257}},{key:"inFSharpPipelineDirectBody",get:function(){return(512&this.flags)>0},set:function(e){e?this.flags|=512:this.flags&=-513}},{key:"canStartJSXElement",get:function(){return(1024&this.flags)>0},set:function(e){e?this.flags|=1024:this.flags&=-1025}},{key:"containsEsc",get:function(){return(2048&this.flags)>0},set:function(e){e?this.flags|=2048:this.flags&=-2049}},{key:"hasTopLevelAwait",get:function(){return(4096&this.flags)>0},set:function(e){e?this.flags|=4096:this.flags&=-4097}}])}();function av(e,t,r){return new dh(r,e-t,e)}var nv=new Set([103,109,115,105,121,117,100,118]),sv=o(function(e){var t=e.startIndex||0;this.type=e.type,this.value=e.value,this.start=t+e.start,this.end=t+e.end,this.loc=new ch(e.startLoc,e.endLoc)}),ov=function(e){function t(t,r){var a;return(a=e.call(this)||this).isLookahead=void 0,a.tokens=[],a.errorHandlers_readInt={invalidDigit:function(e,t,r,n){return!!(a.optionFlags&Oh)&&(a.raise(wh.InvalidDigit,av(e,t,r),{radix:n}),!0)},numericSeparatorInEscapeSequence:a.errorBuilder(wh.NumericSeparatorInEscapeSequence),unexpectedNumericSeparator:a.errorBuilder(wh.UnexpectedNumericSeparator)},a.errorHandlers_readCodePoint=Object.assign({},a.errorHandlers_readInt,{invalidEscapeSequence:a.errorBuilder(wh.InvalidEscapeSequence),invalidCodePoint:a.errorBuilder(wh.InvalidCodePoint)}),a.errorHandlers_readStringContents_string=Object.assign({},a.errorHandlers_readCodePoint,{strictNumericEscape:function(e,t,r){a.recordStrictModeErrors(wh.StrictNumericEscape,av(e,t,r))},unterminated:function(e,t,r){throw a.raise(wh.UnterminatedString,av(e-1,t,r))}}),a.errorHandlers_readStringContents_template=Object.assign({},a.errorHandlers_readCodePoint,{strictNumericEscape:a.errorBuilder(wh.StrictNumericEscape),unterminated:function(e,t,r){throw a.raise(wh.UnterminatedTemplate,av(e,t,r))}}),a.state=new rv,a.state.init(t),a.input=r,a.length=r.length,a.comments=[],a.isLookahead=!1,a}c(t,e);var r=t.prototype;return r.pushToken=function(e){this.tokens.length=this.state.tokensLength,this.tokens.push(e),++this.state.tokensLength},r.next=function(){this.checkKeywordEscapes(),this.optionFlags&Ih&&this.pushToken(new sv(this.state)),this.state.lastTokEndLoc=this.state.endLoc,this.state.lastTokStartLoc=this.state.startLoc,this.nextToken()},r.eat=function(e){return!!this.match(e)&&(this.next(),!0)},r.match=function(e){return this.state.type===e},r.createLookaheadState=function(e){return{pos:e.pos,value:null,type:e.type,start:e.start,end:e.end,context:[this.curContext()],inType:e.inType,startLoc:e.startLoc,lastTokEndLoc:e.lastTokEndLoc,curLine:e.curLine,lineStart:e.lineStart,curPosition:e.curPosition}},r.lookahead=function(){var e=this.state;this.state=this.createLookaheadState(e),this.isLookahead=!0,this.nextToken(),this.isLookahead=!1;var t=this.state;return this.state=e,t},r.nextTokenStart=function(){return this.nextTokenStartSince(this.state.pos)},r.nextTokenStartSince=function(e){return Nx.lastIndex=e,Nx.test(this.input)?Nx.lastIndex:e},r.lookaheadCharCode=function(){return this.lookaheadCharCodeSince(this.state.pos)},r.lookaheadCharCodeSince=function(e){return this.input.charCodeAt(this.nextTokenStartSince(e))},r.nextTokenInLineStart=function(){return this.nextTokenInLineStartSince(this.state.pos)},r.nextTokenInLineStartSince=function(e){return Ox.lastIndex=e,Ox.test(this.input)?Ox.lastIndex:e},r.lookaheadInLineCharCode=function(){return this.input.charCodeAt(this.nextTokenInLineStart())},r.codePointAtPos=function(e){var t=this.input.charCodeAt(e);if(55296==(64512&t)&&++e=this.length?this.finishToken(140):this.getTokenFromCode(this.codePointAtPos(this.state.pos))},r.skipBlockComment=function(e){var t;this.isLookahead||(t=this.state.curPosition());var r=this.state.pos,a=this.input.indexOf(e,r+2);if(-1===a)throw this.raise(wh.UnterminatedComment,this.state.curPosition());for(this.state.pos=a+e.length,Cx.lastIndex=r+2;Cx.test(this.input)&&Cx.lastIndex<=a;)++this.state.curLine,this.state.lineStart=Cx.lastIndex;if(!this.isLookahead){var n={type:"CommentBlock",value:this.input.slice(r+2,a),start:this.sourceToOffsetPos(r),end:this.sourceToOffsetPos(a+e.length),loc:new ch(t,this.state.curPosition())};return this.optionFlags&Ih&&this.pushToken(n),n}},r.skipLineComment=function(e){var t,r=this.state.pos;this.isLookahead||(t=this.state.curPosition());var a=this.input.charCodeAt(this.state.pos+=e);if(this.state.pose))break e;var o=this.skipLineComment(3);void 0!==o&&(this.addComment(o),null==t||t.push(o))}else{if(60!==r||this.inModule||!(this.optionFlags&Mh))break e;var i=this.state.pos;if(33!==this.input.charCodeAt(i+1)||45!==this.input.charCodeAt(i+2)||45!==this.input.charCodeAt(i+3))break e;var d=this.skipLineComment(4);void 0!==d&&(this.addComment(d),null==t||t.push(d))}}}if((null==t?void 0:t.length)>0){var c=this.state.pos,l={start:this.sourceToOffsetPos(e),end:this.sourceToOffsetPos(c),comments:t,leadingNode:null,trailingNode:null,containingNode:null};this.state.commentStack.push(l)}},r.finishToken=function(e,t){this.state.end=this.state.pos,this.state.endLoc=this.state.curPosition();var r=this.state.type;this.state.type=e,this.state.value=t,this.isLookahead||this.updateContext(r)},r.replaceToken=function(e){this.state.type=e,this.updateContext()},r.readToken_numberSign=function(){if(0!==this.state.pos||!this.readToken_interpreter()){var e=this.state.pos+1,t=this.codePointAtPos(e);if(t>=48&&t<=57)throw this.raise(wh.UnexpectedDigitAfterHash,this.state.curPosition());if(123===t||91===t&&this.hasPlugin("recordAndTuple")){if(this.expectPlugin("recordAndTuple"),"bar"===this.getPluginOption("recordAndTuple","syntaxType"))throw this.raise(123===t?wh.RecordExpressionHashIncorrectStartSyntaxType:wh.TupleExpressionHashIncorrectStartSyntaxType,this.state.curPosition());this.state.pos+=2,123===t?this.finishToken(7):this.finishToken(1)}else Ur(t)?(++this.state.pos,this.finishToken(139,this.readWord1(t))):92===t?(++this.state.pos,this.finishToken(139,this.readWord1())):this.finishOp(27,1)}},r.readToken_dot=function(){var e=this.input.charCodeAt(this.state.pos+1);e>=48&&e<=57?this.readNumber(!0):46===e&&46===this.input.charCodeAt(this.state.pos+2)?(this.state.pos+=3,this.finishToken(21)):(++this.state.pos,this.finishToken(16))},r.readToken_slash=function(){61===this.input.charCodeAt(this.state.pos+1)?this.finishOp(31,2):this.finishOp(56,1)},r.readToken_interpreter=function(){if(0!==this.state.pos||this.length<2)return!1;var e=this.input.charCodeAt(this.state.pos+1);if(33!==e)return!1;var t=this.state.pos;for(this.state.pos+=1;!_x(e)&&++this.state.pos=48&&t<=57?(++this.state.pos,this.finishToken(17)):(this.state.pos+=2,this.finishToken(18))},r.getTokenFromCode=function(e){switch(e){case 46:return void this.readToken_dot();case 40:return++this.state.pos,void this.finishToken(10);case 41:return++this.state.pos,void this.finishToken(11);case 59:return++this.state.pos,void this.finishToken(13);case 44:return++this.state.pos,void this.finishToken(12);case 91:if(this.hasPlugin("recordAndTuple")&&124===this.input.charCodeAt(this.state.pos+1)){if("bar"!==this.getPluginOption("recordAndTuple","syntaxType"))throw this.raise(wh.TupleExpressionBarIncorrectStartSyntaxType,this.state.curPosition());this.state.pos+=2,this.finishToken(2)}else++this.state.pos,this.finishToken(0);return;case 93:return++this.state.pos,void this.finishToken(3);case 123:if(this.hasPlugin("recordAndTuple")&&124===this.input.charCodeAt(this.state.pos+1)){if("bar"!==this.getPluginOption("recordAndTuple","syntaxType"))throw this.raise(wh.RecordExpressionBarIncorrectStartSyntaxType,this.state.curPosition());this.state.pos+=2,this.finishToken(6)}else++this.state.pos,this.finishToken(5);return;case 125:return++this.state.pos,void this.finishToken(8);case 58:return void(this.hasPlugin("functionBind")&&58===this.input.charCodeAt(this.state.pos+1)?this.finishOp(15,2):(++this.state.pos,this.finishToken(14)));case 63:return void this.readToken_question();case 96:return void this.readTemplateToken();case 48:var t=this.input.charCodeAt(this.state.pos+1);if(120===t||88===t)return void this.readRadixNumber(16);if(111===t||79===t)return void this.readRadixNumber(8);if(98===t||66===t)return void this.readRadixNumber(2);case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return void this.readNumber(!1);case 34:case 39:return void this.readString(e);case 47:return void this.readToken_slash();case 37:case 42:return void this.readToken_mult_modulo(e);case 124:case 38:return void this.readToken_pipe_amp(e);case 94:return void this.readToken_caret();case 43:case 45:return void this.readToken_plus_min(e);case 60:return void this.readToken_lt();case 62:return void this.readToken_gt();case 61:case 33:return void this.readToken_eq_excl(e);case 126:return void this.finishOp(36,1);case 64:return void this.readToken_atSign();case 35:return void this.readToken_numberSign();case 92:return void this.readWord();default:if(Ur(e))return void this.readWord(e)}throw this.raise(wh.InvalidOrUnexpectedToken,this.state.curPosition(),{unexpected:String.fromCodePoint(e)})},r.finishOp=function(e,t){var r=this.input.slice(this.state.pos,this.state.pos+t);this.state.pos+=t,this.finishToken(e,r)},r.readRegexp=function(){for(var e,t,r=this.state.startLoc,a=this.state.start+1,n=this.state.pos;;++n){if(n>=this.length)throw this.raise(wh.UnterminatedRegExp,lh(r,1));var s=this.input.charCodeAt(n);if(_x(s))throw this.raise(wh.UnterminatedRegExp,lh(r,1));if(e)e=!1;else{if(91===s)t=!0;else if(93===s&&t)t=!1;else if(47===s&&!t)break;e=92===s}}var o=this.input.slice(a,n);++n;for(var i="",d=function(){return lh(r,n+2-a)};n=2&&48===this.input.charCodeAt(t);if(i){var d=this.input.slice(t,this.state.pos);if(this.recordStrictModeErrors(wh.StrictOctalLiteral,r),!this.state.strict){var c=d.indexOf("_");c>0&&this.raise(wh.ZeroDigitNumericSeparator,lh(r,c))}o=i&&!/[89]/.test(d)}var l=this.input.charCodeAt(this.state.pos);if(46!==l||o||(++this.state.pos,this.readInt(10),a=!0,l=this.input.charCodeAt(this.state.pos)),69!==l&&101!==l||o||(43!==(l=this.input.charCodeAt(++this.state.pos))&&45!==l||++this.state.pos,null===this.readInt(10)&&this.raise(wh.InvalidOrMissingExponent,r),a=!0,s=!0,l=this.input.charCodeAt(this.state.pos)),110===l&&((a||i)&&this.raise(wh.InvalidBigIntLiteral,r),++this.state.pos,n=!0),109===l){this.expectPlugin("decimal",this.state.curPosition()),(s||i)&&this.raise(wh.InvalidDecimal,r),++this.state.pos;var u=!0}if(Ur(this.codePointAtPos(this.state.pos)))throw this.raise(wh.NumberIdentifier,this.state.curPosition());var p=this.input.slice(t,this.state.pos).replace(/[_mn]/g,"");if(n)this.finishToken(136,p);else if(u)this.finishToken(137,p);else{var f=o?parseInt(p,8):parseFloat(p);this.finishToken(135,f)}},r.readCodePoint=function(e){var t=da(this.input,this.state.pos,this.state.lineStart,this.state.curLine,e,this.errorHandlers_readCodePoint),r=t.code,a=t.pos;return this.state.pos=a,r},r.readString=function(e){var t=aa(34===e?"double":"single",this.input,this.state.pos+1,this.state.lineStart,this.state.curLine,this.errorHandlers_readStringContents_string),r=t.str,a=t.pos,n=t.curLine,s=t.lineStart;this.state.pos=a+1,this.state.lineStart=s,this.state.curLine=n,this.finishToken(134,r)},r.readTemplateContinuation=function(){this.match(8)||this.unexpected(null,8),this.state.pos--,this.readTemplateToken()},r.readTemplateToken=function(){var e=this.input[this.state.pos],t=aa("template",this.input,this.state.pos+1,this.state.lineStart,this.state.curLine,this.errorHandlers_readStringContents_template),r=t.str,a=t.firstInvalidLoc,n=t.pos,s=t.curLine,o=t.lineStart;this.state.pos=n+1,this.state.lineStart=o,this.state.curLine=s,a&&(this.state.firstInvalidTemplateEscapePos=new dh(a.curLine,a.pos-a.lineStart,this.sourceToOffsetPos(a.pos))),96===this.input.codePointAt(n)?this.finishToken(24,a?null:e+r+"`"):(this.state.pos++,this.finishToken(25,a?null:e+r+"${"))},r.recordStrictModeErrors=function(e,t){var r=t.index;this.state.strict&&!this.state.strictErrors.has(r)?this.raise(e,t):this.state.strictErrors.set(r,[e,t])},r.readWord1=function(e){this.state.containsEsc=!1;var t="",r=this.state.pos,a=this.state.pos;for(void 0!==e&&(this.state.pos+=e<=65535?1:2);this.state.pos=0;o--){var i=s[o];if(i.loc.index===n)return s[o]=e(a,r);if(i.loc.indext.errors.length){var n=this.state;return this.state=t,this.state.tokensLength=n.tokensLength,{node:a,error:n.errors[t.errors.length],thrown:!1,aborted:!1,failState:n}}return{node:a,error:null,thrown:!1,aborted:!1,failState:null}}catch(e){var s=this.state;if(this.state=t,e instanceof SyntaxError)return{node:null,error:e,thrown:!0,aborted:!1,failState:s};if(e===r)return{node:r.node,error:null,thrown:!1,aborted:!0,failState:s};throw e}},r.checkExpressionErrors=function(e,t){if(!e)return!1;var r=e.shorthandAssignLoc,a=e.doubleProtoLoc,n=e.privateKeyLoc,s=e.optionalParametersLoc,o=e.voidPatternLoc;if(!t)return!!(r||a||s||n||o);null!=r&&this.raise(wh.InvalidCoverInitializedName,r),null!=a&&this.raise(wh.DuplicateProto,a),null!=n&&this.raise(wh.UnexpectedPrivateField,n),null!=s&&this.unexpected(s),null!=o&&this.raise(wh.InvalidCoverDiscardElement,o)},r.isLiteralPropertyName=function(){return lb(this.state.type)},r.isPrivateName=function(e){return"PrivateName"===e.type},r.getPrivateNameSV=function(e){return e.id.name},r.hasPropertyAsPrivateName=function(e){return("MemberExpression"===e.type||"OptionalMemberExpression"===e.type)&&this.isPrivateName(e.property)},r.isObjectProperty=function(e){return"ObjectProperty"===e.type},r.isObjectMethod=function(e){return"ObjectMethod"===e.type},r.initializeScopes=function(e){var t=this;void 0===e&&(e="module"===this.options.sourceType);var r=this.state.labels;this.state.labels=[];var a=this.exportedIdentifiers;this.exportedIdentifiers=new Set;var n=this.inModule;this.inModule=e;var s=this.scope,o=this.getScopeHandler();this.scope=new o(this,e);var i=this.prodParam;this.prodParam=new zx;var d=this.classScope;this.classScope=new dv(this);var c=this.expressionScope;return this.expressionScope=new uv(this),function(){t.state.labels=r,t.exportedIdentifiers=a,t.inModule=n,t.scope=s,t.prodParam=i,t.classScope=d,t.expressionScope=c}},r.enterInitialScopes=function(){var e=Gx;(this.inModule||this.optionFlags&Eh)&&(e|=Vx),this.optionFlags&kh&&(e|=Wx);var t=!this.inModule&&"commonjs"===this.options.sourceType;(t||this.optionFlags&Sh)&&(e|=Hx),this.prodParam.enter(e);var r=t?Db:jb;this.optionFlags&Th&&(r|=_b),this.scope.enter(r)},r.checkDestructuringPrivate=function(e){var t=e.privateKeyLoc;null!==t&&this.expectPlugin("destructuringPrivate",t)},o(t)}(ov),gv=o(function(){this.shorthandAssignLoc=null,this.doubleProtoLoc=null,this.privateKeyLoc=null,this.optionalParametersLoc=null,this.voidPatternLoc=null}),yv=o(function(e,t,r){this.type="",this.start=t,this.end=0,this.loc=new ch(r),(null==e?void 0:e.optionFlags)&_h&&(this.range=[t,0]),null!=e&&e.filename&&(this.loc.filename=e.filename)}),mv=yv.prototype;mv.__clone=function(){for(var e=new yv(void 0,this.start,this.loc.start),t=Object.keys(this),r=0,a=t.length;r() => ...`.",ReservedTypeAssertion:"This syntax is reserved in files with the .mts or .cts extension. Use an `as` expression instead.",SetAccessorCannotHaveOptionalParameter:"A 'set' accessor cannot have an optional parameter.",SetAccessorCannotHaveRestParameter:"A 'set' accessor cannot have rest parameter.",SetAccessorCannotHaveReturnType:"A 'set' accessor cannot have a return type annotation.",SingleTypeParameterWithoutTrailingComma:function(e){var t=e.typeParameterName;return"Single type parameter "+t+" should have a trailing comma. Example usage: <"+t+",>."},StaticBlockCannotHaveModifier:"Static class blocks cannot have any modifier.",TupleOptionalAfterType:"A labeled tuple optional element must be declared using a question mark after the name and before the colon (`name?: type`), rather than after the type (`name: type?`).",TypeAnnotationAfterAssign:"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`.",TypeImportCannotSpecifyDefaultAndNamed:"A type-only import can specify a default import or named bindings, but not both.",TypeModifierIsUsedInTypeExports:"The 'type' modifier cannot be used on a named export when 'export type' is used on its export statement.",TypeModifierIsUsedInTypeImports:"The 'type' modifier cannot be used on a named import when 'import type' is used on its import statement.",UnexpectedParameterModifier:"A parameter property is only allowed in a constructor implementation.",UnexpectedReadonly:"'readonly' type modifier is only permitted on array and tuple literal types.",UnexpectedTypeAnnotation:"Did not expect a type annotation here.",UnexpectedTypeCastInParameter:"Unexpected type cast in parameter position.",UnsupportedImportTypeArgument:"Argument in a type import must be a string literal.",UnsupportedParameterPropertyKind:"A parameter property may not be declared using a binding pattern.",UnsupportedSignatureParameterKind:function(e){return"Name in a signature must be an Identifier, ObjectPattern or ArrayPattern, instead got "+e.type+"."},UsingDeclarationInAmbientContext:function(e){return"'"+e+"' declarations are not allowed in ambient contexts."}});function Tv(e){return"private"===e||"public"===e||"protected"===e}function Pv(e){return"in"===e||"out"===e}var Av,kv=0,Cv=1,_v=2;function Iv(e){if("MemberExpression"!==e.type)return!1;var t=e.computed,r=e.property;return(!t||"StringLiteral"===r.type||!("TemplateLiteral"!==r.type||r.expressions.length>0))&&Ov(e.object)}function Dv(e,t){var r,a=e.type;if(null!=(r=e.extra)&&r.parenthesized)return!1;if(t){if("Literal"===a){var n=e.value;if("string"==typeof n||"boolean"==typeof n)return!0}}else if("StringLiteral"===a||"BooleanLiteral"===a)return!0;return!(!Nv(e,t)&&!function(e,t){if("UnaryExpression"===e.type){var r=e.operator,a=e.argument;if("-"===r&&Nv(a,t))return!0}return!1}(e,t))||("TemplateLiteral"===a&&0===e.expressions.length||!!Iv(e))}function Nv(e,t){return t?"Literal"===e.type&&("number"==typeof e.value||"bigint"in e):"NumericLiteral"===e.type||"BigIntLiteral"===e.type}function Ov(e){return"Identifier"===e.type||"MemberExpression"===e.type&&!e.computed&&Ov(e.object)}var Bv=jh(Av||(Av=h(["placeholders"])))({ClassNameIsRequired:"A class name is required.",UnexpectedSpace:"Unexpected space in placeholder."}),Mv=["minimal","fsharp","hack","smart"],Fv=["^^","@@","^","%","#"];var Lv={estree:function(e){return function(e){function t(){return e.apply(this,arguments)||this}c(t,e);var r=t.prototype;return r.parse=function(){var t=Uh(e.prototype.parse.call(this));return this.optionFlags&Ih&&(t.tokens=t.tokens.map(Uh)),t},r.parseRegExpLiteral=function(e){var t=e.pattern,r=e.flags,a=null;try{a=new RegExp(t,r)}catch(e){}var n=this.estreeParseLiteral(a);return n.regex={pattern:t,flags:r},n},r.parseBigIntLiteral=function(e){var t;try{t=BigInt(e)}catch(e){t=null}var r=this.estreeParseLiteral(t);return r.bigint=String(r.value||e),r},r.parseDecimalLiteral=function(e){var t=this.estreeParseLiteral(null);return t.decimal=String(t.value||e),t},r.estreeParseLiteral=function(e){return this.parseLiteral(e,"Literal")},r.parseStringLiteral=function(e){return this.estreeParseLiteral(e)},r.parseNumericLiteral=function(e){return this.estreeParseLiteral(e)},r.parseNullLiteral=function(){return this.estreeParseLiteral(null)},r.parseBooleanLiteral=function(e){return this.estreeParseLiteral(e)},r.estreeParseChainExpression=function(e,t){var r=this.startNodeAtNode(e);return r.expression=e,this.finishNodeAt(r,"ChainExpression",t)},r.directiveToStmt=function(e){var t=e.value;delete e.value,this.castNodeTo(t,"Literal"),t.raw=t.extra.raw,t.value=t.extra.expressionValue;var r=this.castNodeTo(e,"ExpressionStatement");return r.expression=t,r.directive=t.extra.rawValue,delete t.extra,r},r.fillOptionalPropertiesForTSESLint=function(e){},r.cloneEstreeStringLiteral=function(e){var t=e.start,r=e.end,a=e.loc,n=e.range,s=e.raw,o=e.value,i=Object.create(e.constructor.prototype);return i.type="Literal",i.start=t,i.end=r,i.loc=a,i.range=n,i.raw=s,i.value=o,i},r.initFunction=function(t,r){e.prototype.initFunction.call(this,t,r),t.expression=!1},r.checkDeclaration=function(t){null!=t&&this.isObjectProperty(t)?this.checkDeclaration(t.value):e.prototype.checkDeclaration.call(this,t)},r.getObjectOrClassMethodParams=function(e){return e.value.params},r.isValidDirective=function(e){var t;return"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"string"==typeof e.expression.value&&!(null!=(t=e.expression.extra)&&t.parenthesized)},r.parseBlockBody=function(t,r,a,n,s){var o=this;e.prototype.parseBlockBody.call(this,t,r,a,n,s);var i=t.directives.map(function(e){return o.directiveToStmt(e)});t.body=i.concat(t.body),delete t.directives},r.parsePrivateName=function(){var t=e.prototype.parsePrivateName.call(this);return this.getPluginOption("estree","classFeatures")?this.convertPrivateNameToPrivateIdentifier(t):t},r.convertPrivateNameToPrivateIdentifier=function(t){var r=e.prototype.getPrivateNameSV.call(this,t);return delete t.id,t.name=r,this.castNodeTo(t,"PrivateIdentifier")},r.isPrivateName=function(t){return this.getPluginOption("estree","classFeatures")?"PrivateIdentifier"===t.type:e.prototype.isPrivateName.call(this,t)},r.getPrivateNameSV=function(t){return this.getPluginOption("estree","classFeatures")?t.name:e.prototype.getPrivateNameSV.call(this,t)},r.parseLiteral=function(t,r){var a=e.prototype.parseLiteral.call(this,t,r);return a.raw=a.extra.raw,delete a.extra,a},r.parseFunctionBody=function(t,r,a){void 0===a&&(a=!1),e.prototype.parseFunctionBody.call(this,t,r,a),t.expression="BlockStatement"!==t.body.type},r.parseMethod=function(t,r,a,n,s,o,i){void 0===i&&(i=!1);var d=this.startNode();d.kind=t.kind,delete(d=e.prototype.parseMethod.call(this,d,r,a,n,s,o,i)).kind;var c=t.typeParameters;c&&(delete t.typeParameters,d.typeParameters=c,this.resetStartLocationFromNode(d,c));var l=this.castNodeTo(d,"FunctionExpression");return t.value=l,"ClassPrivateMethod"===o&&(t.computed=!1),"ObjectMethod"===o?("method"===t.kind&&(t.kind="init"),t.shorthand=!1,this.finishNode(t,"Property")):this.finishNode(t,"MethodDefinition")},r.nameIsConstructor=function(t){return"Literal"===t.type?"constructor"===t.value:e.prototype.nameIsConstructor.call(this,t)},r.parseClassProperty=function(){for(var t,r=arguments.length,a=new Array(r),n=0;n0&&o.start===n.start&&this.resetStartLocation(n,a)}return n},r.stopParseSubscript=function(t,r){var a=e.prototype.stopParseSubscript.call(this,t,r);return r.optionalChainMember?this.estreeParseChainExpression(a,t.loc.end):a},r.parseMember=function(t,r,a,n,s){var o=e.prototype.parseMember.call(this,t,r,a,n,s);return"OptionalMemberExpression"===o.type?this.castNodeTo(o,"MemberExpression"):o.optional=!1,o},r.isOptionalMemberExpression=function(t){return"ChainExpression"===t.type?"MemberExpression"===t.expression.type:e.prototype.isOptionalMemberExpression.call(this,t)},r.hasPropertyAsPrivateName=function(t){return"ChainExpression"===t.type&&(t=t.expression),e.prototype.hasPropertyAsPrivateName.call(this,t)},r.isObjectProperty=function(e){return"Property"===e.type&&"init"===e.kind&&!e.method},r.isObjectMethod=function(e){return"Property"===e.type&&(e.method||"get"===e.kind||"set"===e.kind)},r.castNodeTo=function(t,r){var a=e.prototype.castNodeTo.call(this,t,r);return this.fillOptionalPropertiesForTSESLint(a),a},r.cloneIdentifier=function(t){var r=e.prototype.cloneIdentifier.call(this,t);return this.fillOptionalPropertiesForTSESLint(r),r},r.cloneStringLiteral=function(t){return"Literal"===t.type?this.cloneEstreeStringLiteral(t):e.prototype.cloneStringLiteral.call(this,t)},r.finishNodeAt=function(t,r,a){return Uh(e.prototype.finishNodeAt.call(this,t,r,a))},r.finishNode=function(t,r){var a=e.prototype.finishNode.call(this,t,r);return this.fillOptionalPropertiesForTSESLint(a),a},r.resetStartLocation=function(t,r){e.prototype.resetStartLocation.call(this,t,r),Uh(t)},r.resetEndLocation=function(t,r){void 0===r&&(r=this.state.lastTokEndLoc),e.prototype.resetEndLocation.call(this,t,r),Uh(t)},o(t)}(e)},jsx:function(e){return function(e){function t(){return e.apply(this,arguments)||this}c(t,e);var r=t.prototype;return r.jsxReadToken=function(){for(var t="",r=this.state.pos;;){if(this.state.pos>=this.length)throw this.raise(Mx.UnterminatedJsxContent,this.state.startLoc);var a=this.input.charCodeAt(this.state.pos);switch(a){case 60:case 123:return this.state.pos===this.state.start?void(60===a&&this.state.canStartJSXElement?(++this.state.pos,this.finishToken(143)):e.prototype.getTokenFromCode.call(this,a)):(t+=this.input.slice(r,this.state.pos),void this.finishToken(142,t));case 38:t+=this.input.slice(r,this.state.pos),t+=this.jsxReadEntity(),r=this.state.pos;break;default:_x(a)?(t+=this.input.slice(r,this.state.pos),t+=this.jsxReadNewLine(!0),r=this.state.pos):++this.state.pos}}},r.jsxReadNewLine=function(e){var t,r=this.input.charCodeAt(this.state.pos);return++this.state.pos,13===r&&10===this.input.charCodeAt(this.state.pos)?(++this.state.pos,t=e?"\n":"\r\n"):t=String.fromCharCode(r),++this.state.curLine,this.state.lineStart=this.state.pos,t},r.jsxReadString=function(e){for(var t="",r=++this.state.pos;;){if(this.state.pos>=this.length)throw this.raise(wh.UnterminatedString,this.state.startLoc);var a=this.input.charCodeAt(this.state.pos);if(a===e)break;38===a?(t+=this.input.slice(r,this.state.pos),t+=this.jsxReadEntity(),r=this.state.pos):_x(a)?(t+=this.input.slice(r,this.state.pos),t+=this.jsxReadNewLine(!1),r=this.state.pos):++this.state.pos}t+=this.input.slice(r,this.state.pos++),this.finishToken(134,t)},r.jsxReadEntity=function(){var e=++this.state.pos;if(35===this.codePointAtPos(this.state.pos)){++this.state.pos;var t=10;120===this.codePointAtPos(this.state.pos)&&(t=16,++this.state.pos);var r=this.readInt(t,void 0,!1,"bail");if(null!==r&&59===this.codePointAtPos(this.state.pos))return++this.state.pos,String.fromCodePoint(r)}else{for(var a=0,n=!1;a++<10&&this.state.posr.index+1&&this.raise(Sx.UnexpectedSpaceBetweenModuloChecks,r),this.eat(10)?(t.value=e.prototype.parseExpression.call(this),this.expect(11),this.finishNode(t,"DeclaredPredicate")):this.finishNode(t,"InferredPredicate")},r.flowParseTypeAndPredicateInitialiser=function(){var e=this.state.inType;this.state.inType=!0,this.expect(14);var t=null,r=null;return this.match(54)?(this.state.inType=e,r=this.flowParsePredicate()):(t=this.flowParseType(),this.state.inType=e,this.match(54)&&(r=this.flowParsePredicate())),[t,r]},r.flowParseDeclareClass=function(e){return this.next(),this.flowParseInterfaceish(e,!0),this.finishNode(e,"DeclareClass")},r.flowParseDeclareFunction=function(e){this.next();var t=e.id=this.parseIdentifier(),r=this.startNode(),a=this.startNode();this.match(47)?r.typeParameters=this.flowParseTypeParameterDeclaration():r.typeParameters=null,this.expect(10);var n=this.flowParseFunctionTypeParams();r.params=n.params,r.rest=n.rest,r.this=n._this,this.expect(11);var s=this.flowParseTypeAndPredicateInitialiser();return r.returnType=s[0],e.predicate=s[1],a.typeAnnotation=this.finishNode(r,"FunctionTypeAnnotation"),t.typeAnnotation=this.finishNode(a,"TypeAnnotation"),this.resetEndLocation(t),this.semicolon(),this.scope.declareName(e.id.name,cx,e.id.loc.start),this.finishNode(e,"DeclareFunction")},r.flowParseDeclare=function(e,t){return this.match(80)?this.flowParseDeclareClass(e):this.match(68)?this.flowParseDeclareFunction(e):this.match(74)?this.flowParseDeclareVariable(e):this.eatContextual(127)?this.match(16)?this.flowParseDeclareModuleExports(e):(t&&this.raise(Sx.NestedDeclareModule,this.state.lastTokStartLoc),this.flowParseDeclareModule(e)):this.isContextual(130)?this.flowParseDeclareTypeAlias(e):this.isContextual(131)?this.flowParseDeclareOpaqueType(e):this.isContextual(129)?this.flowParseDeclareInterface(e):this.match(82)?this.flowParseDeclareExportDeclaration(e,t):void this.unexpected()},r.flowParseDeclareVariable=function(e){return this.next(),e.id=this.flowParseTypeAnnotatableIdentifier(!0),this.scope.declareName(e.id.name,$b,e.id.loc.start),this.semicolon(),this.finishNode(e,"DeclareVariable")},r.flowParseDeclareModule=function(t){var r=this;this.scope.enter(Rb),this.match(134)?t.id=e.prototype.parseExprAtom.call(this):t.id=this.parseIdentifier();var a=t.body=this.startNode(),n=a.body=[];for(this.expect(5);!this.match(8);){var s=this.startNode();this.match(83)?(this.next(),this.isContextual(130)||this.match(87)||this.raise(Sx.InvalidNonTypeImportInDeclareModule,this.state.lastTokStartLoc),e.prototype.parseImport.call(this,s)):(this.expectContextual(125,Sx.UnsupportedStatementInDeclareModule),s=this.flowParseDeclare(s,!0)),n.push(s)}this.scope.exit(),this.expect(8),this.finishNode(a,"BlockStatement");var o=null,i=!1;return n.forEach(function(e){!function(e){return"DeclareExportAllDeclaration"===e.type||"DeclareExportDeclaration"===e.type&&(!e.declaration||"TypeAlias"!==e.declaration.type&&"InterfaceDeclaration"!==e.declaration.type)}(e)?"DeclareModuleExports"===e.type&&(i&&r.raise(Sx.DuplicateDeclareModuleExports,e),"ES"===o&&r.raise(Sx.AmbiguousDeclareModuleKind,e),o="CommonJS",i=!0):("CommonJS"===o&&r.raise(Sx.AmbiguousDeclareModuleKind,e),o="ES")}),t.kind=o||"CommonJS",this.finishNode(t,"DeclareModule")},r.flowParseDeclareExportDeclaration=function(e,t){if(this.expect(82),this.eat(65))return this.match(68)||this.match(80)?e.declaration=this.flowParseDeclare(this.startNode()):(e.declaration=this.flowParseType(),this.semicolon()),e.default=!0,this.finishNode(e,"DeclareExportDeclaration");if(this.match(75)||this.isLet()||(this.isContextual(130)||this.isContextual(129))&&!t){var r=this.state.value;throw this.raise(Sx.UnsupportedDeclareExportKind,this.state.startLoc,{unsupportedExportKind:r,suggestion:Px[r]})}return this.match(74)||this.match(68)||this.match(80)||this.isContextual(131)?(e.declaration=this.flowParseDeclare(this.startNode()),e.default=!1,this.finishNode(e,"DeclareExportDeclaration")):this.match(55)||this.match(5)||this.isContextual(129)||this.isContextual(130)||this.isContextual(131)?"ExportNamedDeclaration"===(e=this.parseExport(e,null)).type?(e.default=!1,delete e.exportKind,this.castNodeTo(e,"DeclareExportDeclaration")):this.castNodeTo(e,"DeclareExportAllDeclaration"):void this.unexpected()},r.flowParseDeclareModuleExports=function(e){return this.next(),this.expectContextual(111),e.typeAnnotation=this.flowParseTypeAnnotation(),this.semicolon(),this.finishNode(e,"DeclareModuleExports")},r.flowParseDeclareTypeAlias=function(e){this.next();var t=this.flowParseTypeAlias(e);return this.castNodeTo(t,"DeclareTypeAlias"),t},r.flowParseDeclareOpaqueType=function(e){this.next();var t=this.flowParseOpaqueType(e,!0);return this.castNodeTo(t,"DeclareOpaqueType"),t},r.flowParseDeclareInterface=function(e){return this.next(),this.flowParseInterfaceish(e,!1),this.finishNode(e,"DeclareInterface")},r.flowParseInterfaceish=function(e,t){if(e.id=this.flowParseRestrictedIdentifier(!t,!0),this.scope.declareName(e.id.name,t?Qb:Jb,e.id.loc.start),this.match(47)?e.typeParameters=this.flowParseTypeParameterDeclaration():e.typeParameters=null,e.extends=[],this.eat(81))do{e.extends.push(this.flowParseInterfaceExtends())}while(!t&&this.eat(12));if(t){if(e.implements=[],e.mixins=[],this.eatContextual(117))do{e.mixins.push(this.flowParseInterfaceExtends())}while(this.eat(12));if(this.eatContextual(113))do{e.implements.push(this.flowParseInterfaceExtends())}while(this.eat(12))}e.body=this.flowParseObjectType({allowStatic:t,allowExact:!1,allowSpread:!1,allowProto:t,allowInexact:!1})},r.flowParseInterfaceExtends=function(){var e=this.startNode();return e.id=this.flowParseQualifiedTypeIdentifier(),this.match(47)?e.typeParameters=this.flowParseTypeParameterInstantiation():e.typeParameters=null,this.finishNode(e,"InterfaceExtends")},r.flowParseInterface=function(e){return this.flowParseInterfaceish(e,!1),this.finishNode(e,"InterfaceDeclaration")},r.checkNotUnderscore=function(e){"_"===e&&this.raise(Sx.UnexpectedReservedUnderscore,this.state.startLoc)},r.checkReservedType=function(e,t,r){Ex.has(e)&&this.raise(r?Sx.AssignReservedType:Sx.UnexpectedReservedType,t,{reservedType:e})},r.flowParseRestrictedIdentifier=function(e,t){return this.checkReservedType(this.state.value,this.state.startLoc,t),this.parseIdentifier(e)},r.flowParseTypeAlias=function(e){return e.id=this.flowParseRestrictedIdentifier(!1,!0),this.scope.declareName(e.id.name,Jb,e.id.loc.start),this.match(47)?e.typeParameters=this.flowParseTypeParameterDeclaration():e.typeParameters=null,e.right=this.flowParseTypeInitialiser(29),this.semicolon(),this.finishNode(e,"TypeAlias")},r.flowParseOpaqueType=function(e,t){return this.expectContextual(130),e.id=this.flowParseRestrictedIdentifier(!0,!0),this.scope.declareName(e.id.name,Jb,e.id.loc.start),this.match(47)?e.typeParameters=this.flowParseTypeParameterDeclaration():e.typeParameters=null,e.supertype=null,this.match(14)&&(e.supertype=this.flowParseTypeInitialiser(14)),e.impltype=null,t||(e.impltype=this.flowParseTypeInitialiser(29)),this.semicolon(),this.finishNode(e,"OpaqueType")},r.flowParseTypeParameter=function(e){void 0===e&&(e=!1);var t=this.state.startLoc,r=this.startNode(),a=this.flowParseVariance(),n=this.flowParseTypeAnnotatableIdentifier();return r.name=n.name,r.variance=a,r.bound=n.typeAnnotation,this.match(29)?(this.eat(29),r.default=this.flowParseType()):e&&this.raise(Sx.MissingTypeParamDefault,t),this.finishNode(r,"TypeParameter")},r.flowParseTypeParameterDeclaration=function(){var e=this.state.inType,t=this.startNode();t.params=[],this.state.inType=!0,this.match(47)||this.match(143)?this.next():this.unexpected();var r=!1;do{var a=this.flowParseTypeParameter(r);t.params.push(a),a.default&&(r=!0),this.match(48)||this.expect(12)}while(!this.match(48));return this.expect(48),this.state.inType=e,this.finishNode(t,"TypeParameterDeclaration")},r.flowInTopLevelContext=function(e){if(this.curContext()===Gh.brace)return e();var t=this.state.context;this.state.context=[t[0]];try{return e()}finally{this.state.context=t}},r.flowParseTypeParameterInstantiationInExpression=function(){if(47===this.reScan_lt())return this.flowParseTypeParameterInstantiation()},r.flowParseTypeParameterInstantiation=function(){var e=this,t=this.startNode(),r=this.state.inType;return this.state.inType=!0,t.params=[],this.flowInTopLevelContext(function(){e.expect(47);var r=e.state.noAnonFunctionType;for(e.state.noAnonFunctionType=!1;!e.match(48);)t.params.push(e.flowParseType()),e.match(48)||e.expect(12);e.state.noAnonFunctionType=r}),this.state.inType=r,this.state.inType||this.curContext()!==Gh.brace||this.reScan_lt_gt(),this.expect(48),this.finishNode(t,"TypeParameterInstantiation")},r.flowParseTypeParameterInstantiationCallOrNew=function(){if(47===this.reScan_lt()){var e=this.startNode(),t=this.state.inType;for(e.params=[],this.state.inType=!0,this.expect(47);!this.match(48);)e.params.push(this.flowParseTypeOrImplicitInstantiation()),this.match(48)||this.expect(12);return this.expect(48),this.state.inType=t,this.finishNode(e,"TypeParameterInstantiation")}},r.flowParseInterfaceType=function(){var e=this.startNode();if(this.expectContextual(129),e.extends=[],this.eat(81))do{e.extends.push(this.flowParseInterfaceExtends())}while(this.eat(12));return e.body=this.flowParseObjectType({allowStatic:!1,allowExact:!1,allowSpread:!1,allowProto:!1,allowInexact:!1}),this.finishNode(e,"InterfaceTypeAnnotation")},r.flowParseObjectPropertyKey=function(){return this.match(135)||this.match(134)?e.prototype.parseExprAtom.call(this):this.parseIdentifier(!0)},r.flowParseObjectTypeIndexer=function(e,t,r){return e.static=t,14===this.lookahead().type?(e.id=this.flowParseObjectPropertyKey(),e.key=this.flowParseTypeInitialiser()):(e.id=null,e.key=this.flowParseType()),this.expect(3),e.value=this.flowParseTypeInitialiser(),e.variance=r,this.finishNode(e,"ObjectTypeIndexer")},r.flowParseObjectTypeInternalSlot=function(e,t){return e.static=t,e.id=this.flowParseObjectPropertyKey(),this.expect(3),this.expect(3),this.match(47)||this.match(10)?(e.method=!0,e.optional=!1,e.value=this.flowParseObjectTypeMethodish(this.startNodeAt(e.loc.start))):(e.method=!1,this.eat(17)&&(e.optional=!0),e.value=this.flowParseTypeInitialiser()),this.finishNode(e,"ObjectTypeInternalSlot")},r.flowParseObjectTypeMethodish=function(e){for(e.params=[],e.rest=null,e.typeParameters=null,e.this=null,this.match(47)&&(e.typeParameters=this.flowParseTypeParameterDeclaration()),this.expect(10),this.match(78)&&(e.this=this.flowParseFunctionTypeParam(!0),e.this.name=null,this.match(11)||this.expect(12));!this.match(11)&&!this.match(21);)e.params.push(this.flowParseFunctionTypeParam(!1)),this.match(11)||this.expect(12);return this.eat(21)&&(e.rest=this.flowParseFunctionTypeParam(!1)),this.expect(11),e.returnType=this.flowParseTypeInitialiser(),this.finishNode(e,"FunctionTypeAnnotation")},r.flowParseObjectTypeCallProperty=function(e,t){var r=this.startNode();return e.static=t,e.value=this.flowParseObjectTypeMethodish(r),this.finishNode(e,"ObjectTypeCallProperty")},r.flowParseObjectType=function(e){var t=e.allowStatic,r=e.allowExact,a=e.allowSpread,n=e.allowProto,s=e.allowInexact,o=this.state.inType;this.state.inType=!0;var i,d,c=this.startNode();c.callProperties=[],c.properties=[],c.indexers=[],c.internalSlots=[];var l=!1;for(r&&this.match(6)?(this.expect(6),i=9,d=!0):(this.expect(5),i=8,d=!1),c.exact=d;!this.match(i);){var u=!1,p=null,f=null,g=this.startNode();if(n&&this.isContextual(118)){var y=this.lookahead();14!==y.type&&17!==y.type&&(this.next(),p=this.state.startLoc,t=!1)}if(t&&this.isContextual(106)){var m=this.lookahead();14!==m.type&&17!==m.type&&(this.next(),u=!0)}var h=this.flowParseVariance();if(this.eat(0))null!=p&&this.unexpected(p),this.eat(0)?(h&&this.unexpected(h.loc.start),c.internalSlots.push(this.flowParseObjectTypeInternalSlot(g,u))):c.indexers.push(this.flowParseObjectTypeIndexer(g,u,h));else if(this.match(10)||this.match(47))null!=p&&this.unexpected(p),h&&this.unexpected(h.loc.start),c.callProperties.push(this.flowParseObjectTypeCallProperty(g,u));else{var b="init";if(this.isContextual(99)||this.isContextual(104))lb(this.lookahead().type)&&(b=this.state.value,this.next());var x=this.flowParseObjectTypeProperty(g,u,p,h,b,a,null!=s?s:!d);null===x?(l=!0,f=this.state.lastTokStartLoc):c.properties.push(x)}this.flowObjectTypeSemicolon(),!f||this.match(8)||this.match(9)||this.raise(Sx.UnexpectedExplicitInexactInObject,f)}this.expect(i),a&&(c.inexact=l);var v=this.finishNode(c,"ObjectTypeAnnotation");return this.state.inType=o,v},r.flowParseObjectTypeProperty=function(e,t,r,a,n,s,o){if(this.eat(21))return this.match(12)||this.match(13)||this.match(8)||this.match(9)?(s?o||this.raise(Sx.InexactInsideExact,this.state.lastTokStartLoc):this.raise(Sx.InexactInsideNonObject,this.state.lastTokStartLoc),a&&this.raise(Sx.InexactVariance,a),null):(s||this.raise(Sx.UnexpectedSpreadType,this.state.lastTokStartLoc),null!=r&&this.unexpected(r),a&&this.raise(Sx.SpreadVariance,a),e.argument=this.flowParseType(),this.finishNode(e,"ObjectTypeSpreadProperty"));e.key=this.flowParseObjectPropertyKey(),e.static=t,e.proto=null!=r,e.kind=n;var i=!1;return this.match(47)||this.match(10)?(e.method=!0,null!=r&&this.unexpected(r),a&&this.unexpected(a.loc.start),e.value=this.flowParseObjectTypeMethodish(this.startNodeAt(e.loc.start)),"get"!==n&&"set"!==n||this.flowCheckGetterSetterParams(e),!s&&"constructor"===e.key.name&&e.value.this&&this.raise(Sx.ThisParamBannedInConstructor,e.value.this)):("init"!==n&&this.unexpected(),e.method=!1,this.eat(17)&&(i=!0),e.value=this.flowParseTypeInitialiser(),e.variance=a),e.optional=i,this.finishNode(e,"ObjectTypeProperty")},r.flowCheckGetterSetterParams=function(e){var t="get"===e.kind?0:1,r=e.value.params.length+(e.value.rest?1:0);e.value.this&&this.raise("get"===e.kind?Sx.GetterMayNotHaveThisParam:Sx.SetterMayNotHaveThisParam,e.value.this),r!==t&&this.raise("get"===e.kind?wh.BadGetterArity:wh.BadSetterArity,e),"set"===e.kind&&e.value.rest&&this.raise(wh.BadSetterRestParameter,e)},r.flowObjectTypeSemicolon=function(){this.eat(13)||this.eat(12)||this.match(8)||this.match(9)||this.unexpected()},r.flowParseQualifiedTypeIdentifier=function(e,t){null!=e||(e=this.state.startLoc);for(var r=t||this.flowParseRestrictedIdentifier(!0);this.eat(16);){var a=this.startNodeAt(e);a.qualification=r,a.id=this.flowParseRestrictedIdentifier(!0),r=this.finishNode(a,"QualifiedTypeIdentifier")}return r},r.flowParseGenericType=function(e,t){var r=this.startNodeAt(e);return r.typeParameters=null,r.id=this.flowParseQualifiedTypeIdentifier(e,t),this.match(47)&&(r.typeParameters=this.flowParseTypeParameterInstantiation()),this.finishNode(r,"GenericTypeAnnotation")},r.flowParseTypeofType=function(){var e=this.startNode();return this.expect(87),e.argument=this.flowParsePrimaryType(),this.finishNode(e,"TypeofTypeAnnotation")},r.flowParseTupleType=function(){var e=this.startNode();for(e.types=[],this.expect(0);this.state.pos0){var g=[].concat(o);if(f.length>0){this.state=s,this.state.noArrowAt=g;for(var y=0;y1&&this.raise(Sx.AmbiguousConditionalArrow,s.startLoc),l&&1===p.length){this.state=s,g.push(p[0].start),this.state.noArrowAt=g;var b=this.tryParseConditionalConsequent();c=b.consequent,l=b.failed}}return this.getArrowLikeExpressions(c,!0),this.state.noArrowAt=o,this.expect(14),i.test=e,i.consequent=c,i.alternate=this.forwardNoArrowParamsConversionAt(i,function(){return a.parseMaybeAssign(void 0,void 0)}),this.finishNode(i,"ConditionalExpression")},r.tryParseConditionalConsequent=function(){this.state.noArrowParamsConversionAt.push(this.state.start);var e=this.parseMaybeAssignAllowIn(),t=!this.match(14);return this.state.noArrowParamsConversionAt.pop(),{consequent:e,failed:t}},r.getArrowLikeExpressions=function(e,t){for(var r=this,a=[e],n=[];0!==a.length;){var s=a.pop();"ArrowFunctionExpression"===s.type&&"BlockStatement"!==s.body.type?(s.typeParameters||!s.returnType?this.finishArrowValidation(s):n.push(s),a.push(s.body)):"ConditionalExpression"===s.type&&(a.push(s.consequent),a.push(s.alternate))}return t?(n.forEach(function(e){return r.finishArrowValidation(e)}),[n,[]]):function(e,t){for(var r=[],a=[],n=0;n1)&&t||this.raise(Sx.TypeCastInPattern,n.typeAnnotation)}return e},r.parseArrayLike=function(t,r,a,n){var s=e.prototype.parseArrayLike.call(this,t,r,a,n);return r&&!this.state.maybeInArrowParameters&&this.toReferencedList(s.elements),s},r.isValidLVal=function(t,r,a){return"TypeCastExpression"===t||e.prototype.isValidLVal.call(this,t,r,a)},r.parseClassProperty=function(t){return this.match(14)&&(t.typeAnnotation=this.flowParseTypeAnnotation()),e.prototype.parseClassProperty.call(this,t)},r.parseClassPrivateProperty=function(t){return this.match(14)&&(t.typeAnnotation=this.flowParseTypeAnnotation()),e.prototype.parseClassPrivateProperty.call(this,t)},r.isClassMethod=function(){return this.match(47)||e.prototype.isClassMethod.call(this)},r.isClassProperty=function(){return this.match(14)||e.prototype.isClassProperty.call(this)},r.isNonstaticConstructor=function(t){return!this.match(14)&&e.prototype.isNonstaticConstructor.call(this,t)},r.pushClassMethod=function(t,r,a,n,s,o){if(r.variance&&this.unexpected(r.variance.loc.start),delete r.variance,this.match(47)&&(r.typeParameters=this.flowParseTypeParameterDeclaration()),e.prototype.pushClassMethod.call(this,t,r,a,n,s,o),r.params&&s){var i=r.params;i.length>0&&this.isThisParam(i[0])&&this.raise(Sx.ThisParamBannedInConstructor,r)}else if("MethodDefinition"===r.type&&s&&r.value.params){var d=r.value.params;d.length>0&&this.isThisParam(d[0])&&this.raise(Sx.ThisParamBannedInConstructor,r)}},r.pushClassPrivateMethod=function(t,r,a,n){r.variance&&this.unexpected(r.variance.loc.start),delete r.variance,this.match(47)&&(r.typeParameters=this.flowParseTypeParameterDeclaration()),e.prototype.pushClassPrivateMethod.call(this,t,r,a,n)},r.parseClassSuper=function(t){if(e.prototype.parseClassSuper.call(this,t),t.superClass&&(this.match(47)||this.match(51))&&(t.superTypeParameters=this.flowParseTypeParameterInstantiationInExpression()),this.isContextual(113)){this.next();var r=t.implements=[];do{var a=this.startNode();a.id=this.flowParseRestrictedIdentifier(!0),this.match(47)?a.typeParameters=this.flowParseTypeParameterInstantiation():a.typeParameters=null,r.push(this.finishNode(a,"ClassImplements"))}while(this.eat(12))}},r.checkGetterSetterParams=function(t){e.prototype.checkGetterSetterParams.call(this,t);var r=this.getObjectOrClassMethodParams(t);if(r.length>0){var a=r[0];this.isThisParam(a)&&"get"===t.kind?this.raise(Sx.GetterMayNotHaveThisParam,a):this.isThisParam(a)&&this.raise(Sx.SetterMayNotHaveThisParam,a)}},r.parsePropertyNamePrefixOperator=function(e){e.variance=this.flowParseVariance()},r.parseObjPropValue=function(t,r,a,n,s,o,i){var d;t.variance&&this.unexpected(t.variance.loc.start),delete t.variance,this.match(47)&&!o&&(d=this.flowParseTypeParameterDeclaration(),this.match(10)||this.unexpected());var c=e.prototype.parseObjPropValue.call(this,t,r,a,n,s,o,i);return d&&((c.value||c).typeParameters=d),c},r.parseFunctionParamType=function(e){return this.eat(17)&&("Identifier"!==e.type&&this.raise(Sx.PatternIsOptional,e),this.isThisParam(e)&&this.raise(Sx.ThisParamMayNotBeOptional,e),e.optional=!0),this.match(14)?e.typeAnnotation=this.flowParseTypeAnnotation():this.isThisParam(e)&&this.raise(Sx.ThisParamAnnotationRequired,e),this.match(29)&&this.isThisParam(e)&&this.raise(Sx.ThisParamNoDefault,e),this.resetEndLocation(e),e},r.parseMaybeDefault=function(t,r){var a=e.prototype.parseMaybeDefault.call(this,t,r);return"AssignmentPattern"===a.type&&a.typeAnnotation&&a.right.start0&&this.raise(Sx.ThisParamMustBeFirst,t.params[s]);e.prototype.checkParams.call(this,t,r,a,n)}},r.parseParenAndDistinguishExpression=function(t){return e.prototype.parseParenAndDistinguishExpression.call(this,t&&!this.state.noArrowAt.includes(this.sourceToOffsetPos(this.state.start)))},r.parseSubscripts=function(t,r,a){var n=this;if("Identifier"===t.type&&"async"===t.name&&this.state.noArrowAt.includes(r.index)){this.next();var s=this.startNodeAt(r);s.callee=t,s.arguments=e.prototype.parseCallExpressionArguments.call(this),t=this.finishNode(s,"CallExpression")}else if("Identifier"===t.type&&"async"===t.name&&this.match(47)){var o=this.state.clone(),i=this.tryParse(function(e){return n.parseAsyncArrowWithTypeParameters(r)||e()},o);if(!i.error&&!i.aborted)return i.node;var d=this.tryParse(function(){return e.prototype.parseSubscripts.call(n,t,r,a)},o);if(d.node&&!d.error)return d.node;if(i.node)return this.state=i.failState,i.node;if(d.node)return this.state=d.failState,d.node;throw i.error||d.error}return e.prototype.parseSubscripts.call(this,t,r,a)},r.parseSubscript=function(t,r,a,n){var s=this;if(this.match(18)&&this.isLookaheadToken_lt()){if(n.optionalChainMember=!0,a)return n.stop=!0,t;this.next();var o=this.startNodeAt(r);return o.callee=t,o.typeArguments=this.flowParseTypeParameterInstantiationInExpression(),this.expect(10),o.arguments=this.parseCallExpressionArguments(),o.optional=!0,this.finishCallExpression(o,!0)}if(!a&&this.shouldParseTypes()&&(this.match(47)||this.match(51))){var i=this.startNodeAt(r);i.callee=t;var d=this.tryParse(function(){return i.typeArguments=s.flowParseTypeParameterInstantiationCallOrNew(),s.expect(10),i.arguments=e.prototype.parseCallExpressionArguments.call(s),n.optionalChainMember&&(i.optional=!1),s.finishCallExpression(i,n.optionalChainMember)});if(d.node)return d.error&&(this.state=d.failState),d.node}return e.prototype.parseSubscript.call(this,t,r,a,n)},r.parseNewCallee=function(t){var r=this;e.prototype.parseNewCallee.call(this,t);var a=null;this.shouldParseTypes()&&this.match(47)&&(a=this.tryParse(function(){return r.flowParseTypeParameterInstantiationCallOrNew()}).node),t.typeArguments=a},r.parseAsyncArrowWithTypeParameters=function(t){var r=this.startNodeAt(t);if(this.parseFunctionParams(r,!1),this.parseArrow(r))return e.prototype.parseArrowExpression.call(this,r,void 0,!0)},r.readToken_mult_modulo=function(t){var r=this.input.charCodeAt(this.state.pos+1);if(42===t&&47===r&&this.state.hasFlowComment)return this.state.hasFlowComment=!1,this.state.pos+=2,void this.nextToken();e.prototype.readToken_mult_modulo.call(this,t)},r.readToken_pipe_amp=function(t){var r=this.input.charCodeAt(this.state.pos+1);124!==t||125!==r?e.prototype.readToken_pipe_amp.call(this,t):this.finishOp(9,2)},r.parseTopLevel=function(t,r){var a=e.prototype.parseTopLevel.call(this,t,r);return this.state.hasFlowComment&&this.raise(Sx.UnterminatedFlowComment,this.state.curPosition()),a},r.skipBlockComment=function(){if(!this.hasPlugin("flowComments")||!this.skipFlowComment())return e.prototype.skipBlockComment.call(this,this.state.hasFlowComment?"*-/":"*/");if(this.state.hasFlowComment)throw this.raise(Sx.NestedFlowComment,this.state.startLoc);this.hasFlowCommentCompletion();var t=this.skipFlowComment();t&&(this.state.pos+=t,this.state.hasFlowComment=!0)},r.skipFlowComment=function(){for(var e=this.state.pos,t=2;[32,9].includes(this.input.charCodeAt(e+t));)t++;var r=this.input.charCodeAt(t+e),a=this.input.charCodeAt(t+e+1);return 58===r&&58===a?t+2:"flow-include"===this.input.slice(t+e,t+e+12)?t+12:58===r&&58!==a&&t},r.hasFlowCommentCompletion=function(){if(-1===this.input.indexOf("*/",this.state.pos))throw this.raise(wh.UnterminatedComment,this.state.curPosition())},r.flowEnumErrorBooleanMemberNotInitialized=function(e,t){var r=t.enumName,a=t.memberName;this.raise(Sx.EnumBooleanMemberNotInitialized,e,{memberName:a,enumName:r})},r.flowEnumErrorInvalidMemberInitializer=function(e,t){return this.raise(t.explicitType?"symbol"===t.explicitType?Sx.EnumInvalidMemberInitializerSymbolType:Sx.EnumInvalidMemberInitializerPrimaryType:Sx.EnumInvalidMemberInitializerUnknownType,e,t)},r.flowEnumErrorNumberMemberNotInitialized=function(e,t){this.raise(Sx.EnumNumberMemberNotInitialized,e,t)},r.flowEnumErrorStringMemberInconsistentlyInitialized=function(e,t){this.raise(Sx.EnumStringMemberInconsistentlyInitialized,e,t)},r.flowEnumMemberInit=function(){var e=this,t=this.state.startLoc,r=function(){return e.match(12)||e.match(8)};switch(this.state.type){case 135:var a=this.parseNumericLiteral(this.state.value);return r()?{type:"number",loc:a.loc.start,value:a}:{type:"invalid",loc:t};case 134:var n=this.parseStringLiteral(this.state.value);return r()?{type:"string",loc:n.loc.start,value:n}:{type:"invalid",loc:t};case 85:case 86:var s=this.parseBooleanLiteral(this.match(85));return r()?{type:"boolean",loc:s.loc.start,value:s}:{type:"invalid",loc:t};default:return{type:"invalid",loc:t}}},r.flowEnumMemberRaw=function(){var e=this.state.startLoc;return{id:this.parseIdentifier(!0),init:this.eat(29)?this.flowEnumMemberInit():{type:"none",loc:e}}},r.flowEnumCheckExplicitTypeMismatch=function(e,t,r){var a=t.explicitType;null!==a&&a!==r&&this.flowEnumErrorInvalidMemberInitializer(e,t)},r.flowEnumMembers=function(e){for(var t=e.enumName,r=e.explicitType,a=new Set,n={booleanMembers:[],numberMembers:[],stringMembers:[],defaultedMembers:[]},s=!1;!this.match(8);){if(this.eat(21)){s=!0;break}var o=this.startNode(),i=this.flowEnumMemberRaw(),d=i.id,c=i.init,l=d.name;if(""!==l){/^[a-z]/.test(l)&&this.raise(Sx.EnumInvalidMemberName,d,{memberName:l,suggestion:l[0].toUpperCase()+l.slice(1),enumName:t}),a.has(l)&&this.raise(Sx.EnumDuplicateMemberName,d,{memberName:l,enumName:t}),a.add(l);var u={enumName:t,explicitType:r,memberName:l};switch(o.id=d,c.type){case"boolean":this.flowEnumCheckExplicitTypeMismatch(c.loc,u,"boolean"),o.init=c.value,n.booleanMembers.push(this.finishNode(o,"EnumBooleanMember"));break;case"number":this.flowEnumCheckExplicitTypeMismatch(c.loc,u,"number"),o.init=c.value,n.numberMembers.push(this.finishNode(o,"EnumNumberMember"));break;case"string":this.flowEnumCheckExplicitTypeMismatch(c.loc,u,"string"),o.init=c.value,n.stringMembers.push(this.finishNode(o,"EnumStringMember"));break;case"invalid":throw this.flowEnumErrorInvalidMemberInitializer(c.loc,u);case"none":switch(r){case"boolean":this.flowEnumErrorBooleanMemberNotInitialized(c.loc,u);break;case"number":this.flowEnumErrorNumberMemberNotInitialized(c.loc,u);break;default:n.defaultedMembers.push(this.finishNode(o,"EnumDefaultedMember"))}}this.match(8)||this.expect(12)}}return{members:n,hasUnknownMembers:s}},r.flowEnumStringMembers=function(e,t,r){var a=r.enumName;if(0===e.length)return t;if(0===t.length)return e;if(t.length>e.length){for(var n=0;n=f){for(var g=0,y=i.defaultedMembers;g=f){for(var h=0,b=i.defaultedMembers;h0&&(this.raise(wh.BadGetterArity,this.state.curPosition()),this.isThisParam(r[a][0])&&this.raise(Sv.AccessorCannotDeclareThisParameter,this.state.curPosition()));else if("set"===r.kind){if(1!==r[a].length)this.raise(wh.BadSetterArity,this.state.curPosition());else{var s=r[a][0];this.isThisParam(s)&&this.raise(Sv.AccessorCannotDeclareThisParameter,this.state.curPosition()),"Identifier"===s.type&&s.optional&&this.raise(Sv.SetAccessorCannotHaveOptionalParameter,this.state.curPosition()),"RestElement"===s.type&&this.raise(Sv.SetAccessorCannotHaveRestParameter,this.state.curPosition())}r[n]&&this.raise(Sv.SetAccessorCannotHaveReturnType,r[n])}else r.kind="method";return this.finishNode(r,"TSMethodSignature")}var o=e;t&&(o.readonly=!0);var i=this.tsTryParseTypeAnnotation();return i&&(o.typeAnnotation=i),this.tsParseTypeMemberSemicolon(),this.finishNode(o,"TSPropertySignature")},r.tsParseTypeMember=function(){var t=this.startNode();if(this.match(10)||this.match(47))return this.tsParseSignatureMember("TSCallSignatureDeclaration",t);if(this.match(77)){var r=this.startNode();return this.next(),this.match(10)||this.match(47)?this.tsParseSignatureMember("TSConstructSignatureDeclaration",t):(t.key=this.createIdentifier(r,"new"),this.tsParsePropertyOrMethodSignature(t,!1))}this.tsParseModifiers({allowedModifiers:["readonly"],disallowedModifiers:["declare","abstract","private","protected","public","static","override"]},t);var a=this.tsTryParseIndexSignature(t);return a||(e.prototype.parsePropertyName.call(this,t),t.computed||"Identifier"!==t.key.type||"get"!==t.key.name&&"set"!==t.key.name||!this.tsTokenCanFollowModifier()||(t.kind=t.key.name,e.prototype.parsePropertyName.call(this,t),this.match(10)||this.match(47)||this.unexpected(null,10)),this.tsParsePropertyOrMethodSignature(t,!!t.readonly))},r.tsParseTypeLiteral=function(){var e=this.startNode();return e.members=this.tsParseObjectTypeMembers(),this.finishNode(e,"TSTypeLiteral")},r.tsParseObjectTypeMembers=function(){this.expect(5);var e=this.tsParseList("TypeMembers",this.tsParseTypeMember.bind(this));return this.expect(8),e},r.tsIsStartOfMappedType=function(){return this.next(),this.eat(53)?this.isContextual(122):(this.isContextual(122)&&this.next(),!!this.match(0)&&(this.next(),!!this.tsIsIdentifier()&&(this.next(),this.match(58))))},r.tsParseMappedType=function(){var e=this.startNode();this.expect(5),this.match(53)?(e.readonly=this.state.value,this.next(),this.expectContextual(122)):this.eatContextual(122)&&(e.readonly=!0),this.expect(0);var t=this.startNode();return t.name=this.tsParseTypeParameterName(),t.constraint=this.tsExpectThenParseType(58),e.typeParameter=this.finishNode(t,"TSTypeParameter"),e.nameType=this.eatContextual(93)?this.tsParseType():null,this.expect(3),this.match(53)?(e.optional=this.state.value,this.next(),this.expect(17)):this.eat(17)&&(e.optional=!0),e.typeAnnotation=this.tsTryParseType(),this.semicolon(),this.expect(8),this.finishNode(e,"TSMappedType")},r.tsParseTupleType=function(){var e=this,t=this.startNode();t.elementTypes=this.tsParseBracketedList("TupleElementTypes",this.tsParseTupleElementType.bind(this),!0,!1);var r=!1;return t.elementTypes.forEach(function(t){var a=t.type;!r||"TSRestType"===a||"TSOptionalType"===a||"TSNamedTupleMember"===a&&t.optional||e.raise(Sv.OptionalTypeBeforeRequired,t),r||(r="TSNamedTupleMember"===a&&t.optional||"TSOptionalType"===a)}),this.finishNode(t,"TSTupleType")},r.tsParseTupleElementType=function(){var e,t,r,a,n,s=this.state.startLoc,o=this.eat(21),i=this.state.startLoc,d=cb(this.state.type)?this.lookaheadCharCode():null;if(58===d)e=!0,r=!1,t=this.parseIdentifier(!0),this.expect(14),a=this.tsParseType();else if(63===d){r=!0;var c=this.state.value,l=this.tsParseNonArrayType();58===this.lookaheadCharCode()?(e=!0,t=this.createIdentifier(this.startNodeAt(i),c),this.expect(17),this.expect(14),a=this.tsParseType()):(e=!1,a=l,this.expect(17))}else a=this.tsParseType(),r=this.eat(17),e=this.eat(14);if(e)t?((n=this.startNodeAt(i)).optional=r,n.label=t,n.elementType=a,this.eat(17)&&(n.optional=!0,this.raise(Sv.TupleOptionalAfterType,this.state.lastTokStartLoc))):((n=this.startNodeAt(i)).optional=r,this.raise(Sv.InvalidTupleMemberLabel,a),n.label=a,n.elementType=this.tsParseType()),a=this.finishNode(n,"TSNamedTupleMember");else if(r){var u=this.startNodeAt(i);u.typeAnnotation=a,a=this.finishNode(u,"TSOptionalType")}if(o){var p=this.startNodeAt(s);p.typeAnnotation=a,a=this.finishNode(p,"TSRestType")}return a},r.tsParseParenthesizedType=function(){var e=this.startNode();return this.expect(10),e.typeAnnotation=this.tsParseType(),this.expect(11),this.finishNode(e,"TSParenthesizedType")},r.tsParseFunctionOrConstructorType=function(e,t){var r=this,a=this.startNode();return"TSConstructorType"===e&&(a.abstract=!!t,t&&this.next(),this.next()),this.tsInAllowConditionalTypesContext(function(){return r.tsFillSignature(19,a)}),this.finishNode(a,e)},r.tsParseLiteralTypeNode=function(){var t=this.startNode();switch(this.state.type){case 135:case 136:case 134:case 85:case 86:t.literal=e.prototype.parseExprAtom.call(this);break;default:this.unexpected()}return this.finishNode(t,"TSLiteralType")},r.tsParseTemplateLiteralType=function(){var t=this.startNode();return t.literal=e.prototype.parseTemplate.call(this,!1),this.finishNode(t,"TSLiteralType")},r.parseTemplateSubstitution=function(){return this.state.inType?this.tsParseType():e.prototype.parseTemplateSubstitution.call(this)},r.tsParseThisTypeOrThisTypePredicate=function(){var e=this.tsParseThisTypeNode();return this.isContextual(116)&&!this.hasPrecedingLineBreak()?this.tsParseThisTypePredicate(e):e},r.tsParseNonArrayType=function(){switch(this.state.type){case 134:case 135:case 136:case 85:case 86:return this.tsParseLiteralTypeNode();case 53:if("-"===this.state.value){var e=this.startNode(),t=this.lookahead();return 135!==t.type&&136!==t.type&&this.unexpected(),e.literal=this.parseMaybeUnary(),this.finishNode(e,"TSLiteralType")}break;case 78:return this.tsParseThisTypeOrThisTypePredicate();case 87:return this.tsParseTypeQuery();case 83:return this.tsParseImportType();case 5:return this.tsLookAhead(this.tsIsStartOfMappedType.bind(this))?this.tsParseMappedType():this.tsParseTypeLiteral();case 0:return this.tsParseTupleType();case 10:return this.tsParseParenthesizedType();case 25:case 24:return this.tsParseTemplateLiteralType();default:var r=this.state.type;if(db(r)||88===r||84===r){var a=88===r?"TSVoidKeyword":84===r?"TSNullKeyword":function(e){switch(e){case"any":return"TSAnyKeyword";case"boolean":return"TSBooleanKeyword";case"bigint":return"TSBigIntKeyword";case"never":return"TSNeverKeyword";case"number":return"TSNumberKeyword";case"object":return"TSObjectKeyword";case"string":return"TSStringKeyword";case"symbol":return"TSSymbolKeyword";case"undefined":return"TSUndefinedKeyword";case"unknown":return"TSUnknownKeyword";default:return}}(this.state.value);if(void 0!==a&&46!==this.lookaheadCharCode()){var n=this.startNode();return this.next(),this.finishNode(n,a)}return this.tsParseTypeReference()}}this.unexpected()},r.tsParseArrayTypeOrHigher=function(){for(var e=this.state.startLoc,t=this.tsParseNonArrayType();!this.hasPrecedingLineBreak()&&this.eat(0);)if(this.match(3)){var r=this.startNodeAt(e);r.elementType=t,this.expect(3),t=this.finishNode(r,"TSArrayType")}else{var a=this.startNodeAt(e);a.objectType=t,a.indexType=this.tsParseType(),this.expect(3),t=this.finishNode(a,"TSIndexedAccessType")}return t},r.tsParseTypeOperator=function(){var e=this.startNode(),t=this.state.value;return this.next(),e.operator=t,e.typeAnnotation=this.tsParseTypeOperatorOrHigher(),"readonly"===t&&this.tsCheckTypeAnnotationForReadOnly(e),this.finishNode(e,"TSTypeOperator")},r.tsCheckTypeAnnotationForReadOnly=function(e){switch(e.typeAnnotation.type){case"TSTupleType":case"TSArrayType":return;default:this.raise(Sv.UnexpectedReadonly,e)}},r.tsParseInferType=function(){var e=this,t=this.startNode();this.expectContextual(115);var r=this.startNode();return r.name=this.tsParseTypeParameterName(),r.constraint=this.tsTryParse(function(){return e.tsParseConstraintForInferType()}),t.typeParameter=this.finishNode(r,"TSTypeParameter"),this.finishNode(t,"TSInferType")},r.tsParseConstraintForInferType=function(){var e=this;if(this.eat(81)){var t=this.tsInDisallowConditionalTypesContext(function(){return e.tsParseType()});if(this.state.inDisallowConditionalTypesContext||!this.match(17))return t}},r.tsParseTypeOperatorOrHigher=function(){var e,t=this;return(e=this.state.type)>=121&&e<=123&&!this.state.containsEsc?this.tsParseTypeOperator():this.isContextual(115)?this.tsParseInferType():this.tsInAllowConditionalTypesContext(function(){return t.tsParseArrayTypeOrHigher()})},r.tsParseUnionOrIntersectionType=function(e,t,r){var a=this.startNode(),n=this.eat(r),s=[];do{s.push(t())}while(this.eat(r));return 1!==s.length||n?(a.types=s,this.finishNode(a,e)):s[0]},r.tsParseIntersectionTypeOrHigher=function(){return this.tsParseUnionOrIntersectionType("TSIntersectionType",this.tsParseTypeOperatorOrHigher.bind(this),45)},r.tsParseUnionTypeOrHigher=function(){return this.tsParseUnionOrIntersectionType("TSUnionType",this.tsParseIntersectionTypeOrHigher.bind(this),43)},r.tsIsStartOfFunctionType=function(){return!!this.match(47)||this.match(10)&&this.tsLookAhead(this.tsIsUnambiguouslyStartOfFunctionType.bind(this))},r.tsSkipParameterStart=function(){if(db(this.state.type)||this.match(78))return this.next(),!0;if(this.match(5)){var t=this.state.errors,r=t.length;try{return this.parseObjectLike(8,!0),t.length===r}catch(e){return!1}}if(this.match(0)){this.next();var a=this.state.errors,n=a.length;try{return e.prototype.parseBindingList.call(this,3,93,vv),a.length===n}catch(e){return!1}}return!1},r.tsIsUnambiguouslyStartOfFunctionType=function(){if(this.next(),this.match(11)||this.match(21))return!0;if(this.tsSkipParameterStart()){if(this.match(14)||this.match(12)||this.match(17)||this.match(29))return!0;if(this.match(11)&&(this.next(),this.match(19)))return!0}return!1},r.tsParseTypeOrTypePredicateAnnotation=function(e){var t=this;return this.tsInType(function(){var r=t.startNode();t.expect(e);var a=t.startNode(),n=!!t.tsTryParse(t.tsParseTypePredicateAsserts.bind(t));if(n&&t.match(78)){var s=t.tsParseThisTypeOrThisTypePredicate();return"TSThisType"===s.type?(a.parameterName=s,a.asserts=!0,a.typeAnnotation=null,s=t.finishNode(a,"TSTypePredicate")):(t.resetStartLocationFromNode(s,a),s.asserts=!0),r.typeAnnotation=s,t.finishNode(r,"TSTypeAnnotation")}var o=t.tsIsIdentifier()&&t.tsTryParse(t.tsParseTypePredicatePrefix.bind(t));if(!o)return n?(a.parameterName=t.parseIdentifier(),a.asserts=n,a.typeAnnotation=null,r.typeAnnotation=t.finishNode(a,"TSTypePredicate"),t.finishNode(r,"TSTypeAnnotation")):t.tsParseTypeAnnotation(!1,r);var i=t.tsParseTypeAnnotation(!1);return a.parameterName=o,a.typeAnnotation=i,a.asserts=n,r.typeAnnotation=t.finishNode(a,"TSTypePredicate"),t.finishNode(r,"TSTypeAnnotation")})},r.tsTryParseTypeOrTypePredicateAnnotation=function(){if(this.match(14))return this.tsParseTypeOrTypePredicateAnnotation(14)},r.tsTryParseTypeAnnotation=function(){if(this.match(14))return this.tsParseTypeAnnotation()},r.tsTryParseType=function(){return this.tsEatThenParseType(14)},r.tsParseTypePredicatePrefix=function(){var e=this.parseIdentifier();if(this.isContextual(116)&&!this.hasPrecedingLineBreak())return this.next(),e},r.tsParseTypePredicateAsserts=function(){if(109!==this.state.type)return!1;var e=this.state.containsEsc;return this.next(),!(!db(this.state.type)&&!this.match(78))&&(e&&this.raise(wh.InvalidEscapedReservedWord,this.state.lastTokStartLoc,{reservedWord:"asserts"}),!0)},r.tsParseTypeAnnotation=function(e,t){var r=this;return void 0===e&&(e=!0),void 0===t&&(t=this.startNode()),this.tsInType(function(){e&&r.expect(14),t.typeAnnotation=r.tsParseType()}),this.finishNode(t,"TSTypeAnnotation")},r.tsParseType=function(){var e=this;Ev(this.state.inType);var t=this.tsParseNonConditionalType();if(this.state.inDisallowConditionalTypesContext||this.hasPrecedingLineBreak()||!this.eat(81))return t;var r=this.startNodeAtNode(t);return r.checkType=t,r.extendsType=this.tsInDisallowConditionalTypesContext(function(){return e.tsParseNonConditionalType()}),this.expect(17),r.trueType=this.tsInAllowConditionalTypesContext(function(){return e.tsParseType()}),this.expect(14),r.falseType=this.tsInAllowConditionalTypesContext(function(){return e.tsParseType()}),this.finishNode(r,"TSConditionalType")},r.isAbstractConstructorSignature=function(){return this.isContextual(124)&&this.isLookaheadContextual("new")},r.tsParseNonConditionalType=function(){return this.tsIsStartOfFunctionType()?this.tsParseFunctionOrConstructorType("TSFunctionType"):this.match(77)?this.tsParseFunctionOrConstructorType("TSConstructorType"):this.isAbstractConstructorSignature()?this.tsParseFunctionOrConstructorType("TSConstructorType",!0):this.tsParseUnionTypeOrHigher()},r.tsParseTypeAssertion=function(){var e=this;this.getPluginOption("typescript","disallowAmbiguousJSXLike")&&this.raise(Sv.ReservedTypeAssertion,this.state.startLoc);var t=this.startNode();return t.typeAnnotation=this.tsInType(function(){return e.next(),e.match(75)?e.tsParseTypeReference():e.tsParseType()}),this.expect(48),t.expression=this.parseMaybeUnary(),this.finishNode(t,"TSTypeAssertion")},r.tsParseHeritageClause=function(e){var t=this,r=this.state.startLoc,a=this.tsParseDelimitedList("HeritageClauseElement",function(){var e=t.startNode();return e.expression=t.tsParseEntityName(Cv|_v),t.match(47)&&(e.typeParameters=t.tsParseTypeArguments()),t.finishNode(e,"TSExpressionWithTypeArguments")});return a.length||this.raise(Sv.EmptyHeritageClauseType,r,{token:e}),a},r.tsParseInterfaceDeclaration=function(e,t){if(void 0===t&&(t={}),this.hasFollowingLineBreak())return null;this.expectContextual(129),t.declare&&(e.declare=!0),db(this.state.type)?(e.id=this.parseIdentifier(),this.checkIdentifier(e.id,Zb)):(e.id=null,this.raise(Sv.MissingInterfaceName,this.state.startLoc)),e.typeParameters=this.tsTryParseTypeParameters(this.tsParseInOutConstModifiers),this.eat(81)&&(e.extends=this.tsParseHeritageClause("extends"));var r=this.startNode();return r.body=this.tsInType(this.tsParseObjectTypeMembers.bind(this)),e.body=this.finishNode(r,"TSInterfaceBody"),this.finishNode(e,"TSInterfaceDeclaration")},r.tsParseTypeAliasDeclaration=function(e){var t=this;return e.id=this.parseIdentifier(),this.checkIdentifier(e.id,ex),e.typeAnnotation=this.tsInType(function(){if(e.typeParameters=t.tsTryParseTypeParameters(t.tsParseInOutModifiers),t.expect(29),t.isContextual(114)&&46!==t.lookaheadCharCode()){var r=t.startNode();return t.next(),t.finishNode(r,"TSIntrinsicKeyword")}return t.tsParseType()}),this.semicolon(),this.finishNode(e,"TSTypeAliasDeclaration")},r.tsInTopLevelContext=function(e){if(this.curContext()===Gh.brace)return e();var t=this.state.context;this.state.context=[t[0]];try{return e()}finally{this.state.context=t}},r.tsInType=function(e){var t=this.state.inType;this.state.inType=!0;try{return e()}finally{this.state.inType=t}},r.tsInDisallowConditionalTypesContext=function(e){var t=this.state.inDisallowConditionalTypesContext;this.state.inDisallowConditionalTypesContext=!0;try{return e()}finally{this.state.inDisallowConditionalTypesContext=t}},r.tsInAllowConditionalTypesContext=function(e){var t=this.state.inDisallowConditionalTypesContext;this.state.inDisallowConditionalTypesContext=!1;try{return e()}finally{this.state.inDisallowConditionalTypesContext=t}},r.tsEatThenParseType=function(e){if(this.match(e))return this.tsNextThenParseType()},r.tsExpectThenParseType=function(e){var t=this;return this.tsInType(function(){return t.expect(e),t.tsParseType()})},r.tsNextThenParseType=function(){var e=this;return this.tsInType(function(){return e.next(),e.tsParseType()})},r.tsParseEnumMember=function(){var t=this.startNode();return t.id=this.match(134)?e.prototype.parseStringLiteral.call(this,this.state.value):this.parseIdentifier(!0),this.eat(29)&&(t.initializer=e.prototype.parseMaybeAssignAllowIn.call(this)),this.finishNode(t,"TSEnumMember")},r.tsParseEnumDeclaration=function(e,t){return void 0===t&&(t={}),t.const&&(e.const=!0),t.declare&&(e.declare=!0),this.expectContextual(126),e.id=this.parseIdentifier(),this.checkIdentifier(e.id,e.const?sx:tx),this.expect(5),e.members=this.tsParseDelimitedList("EnumMembers",this.tsParseEnumMember.bind(this)),this.expect(8),this.finishNode(e,"TSEnumDeclaration")},r.tsParseEnumBody=function(){var e=this.startNode();return this.expect(5),e.members=this.tsParseDelimitedList("EnumMembers",this.tsParseEnumMember.bind(this)),this.expect(8),this.finishNode(e,"TSEnumBody")},r.tsParseModuleBlock=function(){var t=this.startNode();return this.scope.enter(Rb),this.expect(5),e.prototype.parseBlockOrModuleBlockBody.call(this,t.body=[],void 0,!0,8),this.scope.exit(),this.finishNode(t,"TSModuleBlock")},r.tsParseModuleOrNamespaceDeclaration=function(e,t){if(void 0===t&&(t=!1),e.id=this.parseIdentifier(),t||this.checkIdentifier(e.id,ox),this.eat(16)){var r=this.startNode();this.tsParseModuleOrNamespaceDeclaration(r,!0),e.body=r}else this.scope.enter(Ib),this.prodParam.enter(Gx),e.body=this.tsParseModuleBlock(),this.prodParam.exit(),this.scope.exit();return this.finishNode(e,"TSModuleDeclaration")},r.tsParseAmbientExternalModuleDeclaration=function(t){return this.isContextual(112)?(t.kind="global",t.global=!0,t.id=this.parseIdentifier()):this.match(134)?(t.kind="module",t.id=e.prototype.parseStringLiteral.call(this,this.state.value)):this.unexpected(),this.match(5)?(this.scope.enter(Ib),this.prodParam.enter(Gx),t.body=this.tsParseModuleBlock(),this.prodParam.exit(),this.scope.exit()):this.semicolon(),this.finishNode(t,"TSModuleDeclaration")},r.tsParseImportEqualsDeclaration=function(e,t,r){e.isExport=r||!1,e.id=t||this.parseIdentifier(),this.checkIdentifier(e.id,dx),this.expect(29);var a=this.tsParseModuleReference();return"type"===e.importKind&&"TSExternalModuleReference"!==a.type&&this.raise(Sv.ImportAliasHasImportType,a),e.moduleReference=a,this.semicolon(),this.finishNode(e,"TSImportEqualsDeclaration")},r.tsIsExternalModuleReference=function(){return this.isContextual(119)&&40===this.lookaheadCharCode()},r.tsParseModuleReference=function(){return this.tsIsExternalModuleReference()?this.tsParseExternalModuleReference():this.tsParseEntityName(kv)},r.tsParseExternalModuleReference=function(){var t=this.startNode();return this.expectContextual(119),this.expect(10),this.match(134)||this.unexpected(),t.expression=e.prototype.parseExprAtom.call(this),this.expect(11),this.sawUnambiguousESM=!0,this.finishNode(t,"TSExternalModuleReference")},r.tsLookAhead=function(e){var t=this.state.clone(),r=e();return this.state=t,r},r.tsTryParseAndCatch=function(e){var t=this.tryParse(function(t){return e()||t()});if(!t.aborted&&t.node)return t.error&&(this.state=t.failState),t.node},r.tsTryParse=function(e){var t=this.state.clone(),r=e();if(void 0!==r&&!1!==r)return r;this.state=t},r.tsTryParseDeclare=function(t){var r=this;if(!this.isLineTerminator()){var a=this.state.type;return this.tsInAmbientContext(function(){switch(a){case 68:return t.declare=!0,e.prototype.parseFunctionStatement.call(r,t,!1,!1);case 80:return t.declare=!0,r.parseClass(t,!0,!1);case 126:return r.tsParseEnumDeclaration(t,{declare:!0});case 112:return r.tsParseAmbientExternalModuleDeclaration(t);case 100:if(r.state.containsEsc)return;case 75:case 74:return r.match(75)&&r.isLookaheadContextual("enum")?(r.expect(75),r.tsParseEnumDeclaration(t,{const:!0,declare:!0})):(t.declare=!0,r.parseVarStatement(t,r.state.value,!0));case 107:if(r.isUsing())return r.raise(Sv.InvalidModifierOnUsingDeclaration,r.state.startLoc,"declare"),t.declare=!0,r.parseVarStatement(t,"using",!0);break;case 96:if(r.isAwaitUsing())return r.raise(Sv.InvalidModifierOnAwaitUsingDeclaration,r.state.startLoc,"declare"),t.declare=!0,r.next(),r.parseVarStatement(t,"await using",!0);break;case 129:var n=r.tsParseInterfaceDeclaration(t,{declare:!0});if(n)return n;default:if(db(a))return r.tsParseDeclaration(t,r.state.value,!0,null)}})}},r.tsTryParseExportDeclaration=function(){return this.tsParseDeclaration(this.startNode(),this.state.value,!0,null)},r.tsParseExpressionStatement=function(e,t,r){switch(t.name){case"declare":var a=this.tsTryParseDeclare(e);return a&&(a.declare=!0),a;case"global":if(this.match(5)){this.scope.enter(Ib),this.prodParam.enter(Gx);var n=e;return n.kind="global",e.global=!0,n.id=t,n.body=this.tsParseModuleBlock(),this.scope.exit(),this.prodParam.exit(),this.finishNode(n,"TSModuleDeclaration")}break;default:return this.tsParseDeclaration(e,t.name,!1,r)}},r.tsParseDeclaration=function(e,t,r,a){switch(t){case"abstract":if(this.tsCheckLineTerminator(r)&&(this.match(80)||db(this.state.type)))return this.tsParseAbstractDeclaration(e,a);break;case"module":if(this.tsCheckLineTerminator(r)){if(this.match(134))return this.tsParseAmbientExternalModuleDeclaration(e);if(db(this.state.type))return e.kind="module",this.tsParseModuleOrNamespaceDeclaration(e)}break;case"namespace":if(this.tsCheckLineTerminator(r)&&db(this.state.type))return e.kind="namespace",this.tsParseModuleOrNamespaceDeclaration(e);break;case"type":if(this.tsCheckLineTerminator(r)&&db(this.state.type))return this.tsParseTypeAliasDeclaration(e)}},r.tsCheckLineTerminator=function(e){return e?!this.hasFollowingLineBreak()&&(this.next(),!0):!this.isLineTerminator()},r.tsTryParseGenericAsyncArrowFunction=function(t){var r=this;if(this.match(47)){var a=this.state.maybeInArrowParameters;this.state.maybeInArrowParameters=!0;var n=this.tsTryParseAndCatch(function(){var a=r.startNodeAt(t);return a.typeParameters=r.tsParseTypeParameters(r.tsParseConstModifier),e.prototype.parseFunctionParams.call(r,a),a.returnType=r.tsTryParseTypeOrTypePredicateAnnotation(),r.expect(19),a});if(this.state.maybeInArrowParameters=a,n)return e.prototype.parseArrowExpression.call(this,n,null,!0)}},r.tsParseTypeArgumentsInExpression=function(){if(47===this.reScan_lt())return this.tsParseTypeArguments()},r.tsParseTypeArguments=function(){var e=this,t=this.startNode();return t.params=this.tsInType(function(){return e.tsInTopLevelContext(function(){return e.expect(47),e.tsParseDelimitedList("TypeParametersOrArguments",e.tsParseType.bind(e))})}),0===t.params.length?this.raise(Sv.EmptyTypeArguments,t):this.state.inType||this.curContext()!==Gh.brace||this.reScan_lt_gt(),this.expect(48),this.finishNode(t,"TSTypeParameterInstantiation")},r.tsIsDeclarationStart=function(){return(e=this.state.type)>=124&&e<=130;var e},r.isExportDefaultSpecifier=function(){return!this.tsIsDeclarationStart()&&e.prototype.isExportDefaultSpecifier.call(this)},r.parseBindingElement=function(e,t){var r=t.length?t[0].loc.start:this.state.startLoc,a={};this.tsParseModifiers({allowedModifiers:["public","private","protected","override","readonly"]},a);var n=a.accessibility,s=a.override,o=a.readonly;e&jv||!(n||o||s)||this.raise(Sv.UnexpectedParameterModifier,r);var i=this.parseMaybeDefault();e&Rv&&this.parseFunctionParamType(i);var d=this.parseMaybeDefault(i.loc.start,i);if(n||o||s){var c=this.startNodeAt(r);return t.length&&(c.decorators=t),n&&(c.accessibility=n),o&&(c.readonly=o),s&&(c.override=s),"Identifier"!==d.type&&"AssignmentPattern"!==d.type&&this.raise(Sv.UnsupportedParameterPropertyKind,c),c.parameter=d,this.finishNode(c,"TSParameterProperty")}return t.length&&(i.decorators=t),d},r.isSimpleParameter=function(t){return"TSParameterProperty"===t.type&&e.prototype.isSimpleParameter.call(this,t.parameter)||e.prototype.isSimpleParameter.call(this,t)},r.tsDisallowOptionalPattern=function(e){for(var t=0,r=e.params;ta&&!this.hasPrecedingLineBreak()&&(this.isContextual(93)||(n=this.isContextual(120)))){var o=this.startNodeAt(r);return o.expression=t,o.typeAnnotation=this.tsInType(function(){return s.next(),s.match(75)?(n&&s.raise(wh.UnexpectedKeyword,s.state.startLoc,{keyword:"const"}),s.tsParseTypeReference()):s.tsParseType()}),this.finishNode(o,n?"TSSatisfiesExpression":"TSAsExpression"),this.reScan_lt_gt(),this.parseExprOp(o,r,a)}return e.prototype.parseExprOp.call(this,t,r,a)},r.checkReservedWord=function(t,r,a,n){this.state.isAmbientContext||e.prototype.checkReservedWord.call(this,t,r,a,n)},r.checkImportReflection=function(t){e.prototype.checkImportReflection.call(this,t),t.module&&"value"!==t.importKind&&this.raise(Sv.ImportReflectionHasImportType,t.specifiers[0].loc.start)},r.checkDuplicateExports=function(){},r.isPotentialImportPhase=function(t){if(e.prototype.isPotentialImportPhase.call(this,t))return!0;if(this.isContextual(130)){var r=this.lookaheadCharCode();return t?123===r||42===r:61!==r}return!t&&this.isContextual(87)},r.applyImportPhase=function(t,r,a,n){e.prototype.applyImportPhase.call(this,t,r,a,n),r?t.exportKind="type"===a?"type":"value":t.importKind="type"===a||"typeof"===a?a:"value"},r.parseImport=function(t){if(this.match(134))return t.importKind="value",e.prototype.parseImport.call(this,t);var r;if(db(this.state.type)&&61===this.lookaheadCharCode())return t.importKind="value",this.tsParseImportEqualsDeclaration(t);if(this.isContextual(130)){var a=this.parseMaybeImportPhase(t,!1);if(61===this.lookaheadCharCode())return this.tsParseImportEqualsDeclaration(t,a);r=e.prototype.parseImportSpecifiersAndAfter.call(this,t,a)}else r=e.prototype.parseImport.call(this,t);return"type"===r.importKind&&r.specifiers.length>1&&"ImportDefaultSpecifier"===r.specifiers[0].type&&this.raise(Sv.TypeImportCannotSpecifyDefaultAndNamed,r),r},r.parseExport=function(t,r){if(this.match(83)){var a=t;this.next();var n=null;return this.isContextual(130)&&this.isPotentialImportPhase(!1)?n=this.parseMaybeImportPhase(a,!1):a.importKind="value",this.tsParseImportEqualsDeclaration(a,n,!0)}if(this.eat(29)){var s=t;return s.expression=e.prototype.parseExpression.call(this),this.semicolon(),this.sawUnambiguousESM=!0,this.finishNode(s,"TSExportAssignment")}if(this.eatContextual(93)){var o=t;return this.expectContextual(128),o.id=this.parseIdentifier(),this.semicolon(),this.finishNode(o,"TSNamespaceExportDeclaration")}return e.prototype.parseExport.call(this,t,r)},r.isAbstractClass=function(){return this.isContextual(124)&&this.isLookaheadContextual("class")},r.parseExportDefaultExpression=function(){if(this.isAbstractClass()){var t=this.startNode();return this.next(),t.abstract=!0,this.parseClass(t,!0,!0)}if(this.match(129)){var r=this.tsParseInterfaceDeclaration(this.startNode());if(r)return r}return e.prototype.parseExportDefaultExpression.call(this)},r.parseVarStatement=function(t,r,a){void 0===a&&(a=!1);var n=this.state.isAmbientContext,s=e.prototype.parseVarStatement.call(this,t,r,a||n);if(!n)return s;if(!t.declare&&("using"===r||"await using"===r))return this.raiseOverwrite(Sv.UsingDeclarationInAmbientContext,t,r),s;for(var o=0,i=s.declarations;othis.offsetToSourcePos(this.state.lastTokEndLoc.index)&&this.raise(Bv.UnexpectedSpace,this.state.lastTokEndLoc)},o(t)}(e)}},Uv=Object.keys(Lv),qv=function(e){function t(){return e.apply(this,arguments)||this}c(t,e);var r=t.prototype;return r.checkProto=function(e,t,r,a){if("SpreadElement"===e.type||this.isObjectMethod(e)||e.computed||e.shorthand)return r;var n=e.key;return"__proto__"===("Identifier"===n.type?n.name:n.value)?t?(this.raise(wh.RecordNoProto,n),!0):(r&&(a?null===a.doubleProtoLoc&&(a.doubleProtoLoc=n.loc.start):this.raise(wh.DuplicateProto,n)),!0):r},r.shouldExitDescending=function(e,t){return"ArrowFunctionExpression"===e.type&&this.offsetToSourcePos(e.start)===t},r.getExpression=function(){if(this.enterInitialScopes(),this.nextToken(),this.match(140))throw this.raise(wh.ParseExpressionEmptyInput,this.state.startLoc);var e=this.parseExpression();if(!this.match(140))throw this.raise(wh.ParseExpressionExpectsEOF,this.state.startLoc,{unexpected:this.input.codePointAt(this.state.start)});return this.finalizeRemainingComments(),e.comments=this.comments,e.errors=this.state.errors,this.optionFlags&Ih&&(e.tokens=this.tokens),e},r.parseExpression=function(e,t){var r=this;return e?this.disallowInAnd(function(){return r.parseExpressionBase(t)}):this.allowInAnd(function(){return r.parseExpressionBase(t)})},r.parseExpressionBase=function(e){var t=this.state.startLoc,r=this.parseMaybeAssign(e);if(this.match(12)){var a=this.startNodeAt(t);for(a.expressions=[r];this.eat(12);)a.expressions.push(this.parseMaybeAssign(e));return this.toReferencedList(a.expressions),this.finishNode(a,"SequenceExpression")}return r},r.parseMaybeAssignDisallowIn=function(e,t){var r=this;return this.disallowInAnd(function(){return r.parseMaybeAssign(e,t)})},r.parseMaybeAssignAllowIn=function(e,t){var r=this;return this.allowInAnd(function(){return r.parseMaybeAssign(e,t)})},r.setOptionalParametersError=function(e){e.optionalParametersLoc=this.state.startLoc},r.parseMaybeAssign=function(e,t){var r,a=this.state.startLoc,n=this.isContextual(108);if(n&&this.prodParam.hasYield){this.next();var s=this.parseYield(a);return t&&(s=t.call(this,s,a)),s}e?r=!1:(e=new gv,r=!0);var o=this.state.type;(10===o||db(o))&&(this.state.potentialArrowAt=this.state.start);var i,d=this.parseMaybeConditional(e);if(t&&(d=t.call(this,d,a)),(i=this.state.type)>=29&&i<=33){var c=this.startNodeAt(a),l=this.state.value;if(c.operator=l,this.match(29)){this.toAssignable(d,!0),c.left=d;var u=a.index;null!=e.doubleProtoLoc&&e.doubleProtoLoc.index>=u&&(e.doubleProtoLoc=null),null!=e.shorthandAssignLoc&&e.shorthandAssignLoc.index>=u&&(e.shorthandAssignLoc=null),null!=e.privateKeyLoc&&e.privateKeyLoc.index>=u&&(this.checkDestructuringPrivate(e),e.privateKeyLoc=null),null!=e.voidPatternLoc&&e.voidPatternLoc.index>=u&&(e.voidPatternLoc=null)}else c.left=d;return this.next(),c.right=this.parseMaybeAssign(),this.checkLVal(d,this.finishNode(c,"AssignmentExpression")),c}if(r&&this.checkExpressionErrors(e,!0),n){var p=this.state.type;if((this.hasPlugin("v8intrinsic")?ub(p):ub(p)&&!this.match(54))&&!this.isAmbiguousPrefixOrIdentifier())return this.raiseOverwrite(wh.YieldNotInGeneratorFunction,a),this.parseYield(a)}return d},r.parseMaybeConditional=function(e){var t=this.state.startLoc,r=this.state.potentialArrowAt,a=this.parseExprOps(e);return this.shouldExitDescending(a,r)?a:this.parseConditional(a,t,e)},r.parseConditional=function(e,t,r){if(this.eat(17)){var a=this.startNodeAt(t);return a.test=e,a.consequent=this.parseMaybeAssignAllowIn(),this.expect(14),a.alternate=this.parseMaybeAssign(),this.finishNode(a,"ConditionalExpression")}return e},r.parseMaybeUnaryOrPrivate=function(e){return this.match(139)?this.parsePrivateName():this.parseMaybeUnary(e)},r.parseExprOps=function(e){var t=this.state.startLoc,r=this.state.potentialArrowAt,a=this.parseMaybeUnaryOrPrivate(e);return this.shouldExitDescending(a,r)?a:this.parseExprOp(a,t,-1)},r.parseExprOp=function(e,t,r){if(this.isPrivateName(e)){var a=this.getPrivateNameSV(e);(r>=mb(58)||!this.prodParam.hasIn||!this.match(58))&&this.raise(wh.PrivateInExpectedIn,e,{identifierName:a}),this.classScope.usePrivateName(a,e.loc.start)}var n,s=this.state.type;if((n=s)>=39&&n<=59&&(this.prodParam.hasIn||!this.match(58))){var o=mb(s);if(o>r){if(39===s){if(this.expectPlugin("pipelineOperator"),this.state.inFSharpPipelineDirectBody)return e;this.checkPipelineAtInfixOperator(e,t)}var i=this.startNodeAt(t);i.left=e,i.operator=this.state.value;var d=41===s||42===s,c=40===s;if(c&&(o=mb(42)),this.next(),39===s&&this.hasPlugin(["pipelineOperator",{proposal:"minimal"}])&&96===this.state.type&&this.prodParam.hasAwait)throw this.raise(wh.UnexpectedAwaitAfterPipelineBody,this.state.startLoc);i.right=this.parseExprOpRightExpr(s,o);var l=this.finishNode(i,d||c?"LogicalExpression":"BinaryExpression"),u=this.state.type;if(c&&(41===u||42===u)||d&&40===u)throw this.raise(wh.MixingCoalesceWithLogical,this.state.startLoc);return this.parseExprOp(l,t,r)}}return e},r.parseExprOpRightExpr=function(e,t){var r=this,a=this.state.startLoc;if(39===e){switch(this.getPluginOption("pipelineOperator","proposal")){case"hack":return this.withTopicBindingContext(function(){return r.parseHackPipeBody()});case"fsharp":return this.withSoloAwaitPermittingContext(function(){return r.parseFSharpPipelineBody(t)})}if("smart"===this.getPluginOption("pipelineOperator","proposal"))return this.withTopicBindingContext(function(){if(r.prodParam.hasYield&&r.isContextual(108))throw r.raise(wh.PipeBodyIsTighter,r.state.startLoc);return r.parseSmartPipelineBodyInStyle(r.parseExprOpBaseRightExpr(e,t),a)})}return this.parseExprOpBaseRightExpr(e,t)},r.parseExprOpBaseRightExpr=function(e,t){var r=this.state.startLoc;return this.parseExprOp(this.parseMaybeUnaryOrPrivate(),r,57===e?t-1:t)},r.parseHackPipeBody=function(){var e,t=this.state.startLoc,r=this.parseMaybeAssign();return!bh.has(r.type)||null!=(e=r.extra)&&e.parenthesized||this.raise(wh.PipeUnparenthesizedBody,t,{type:r.type}),this.topicReferenceWasUsedInCurrentContext()||this.raise(wh.PipeTopicUnused,t),r},r.checkExponentialAfterUnary=function(e){this.match(57)&&this.raise(wh.UnexpectedTokenUnaryExponentiation,e.argument)},r.parseMaybeUnary=function(e,t){var r=this.state.startLoc,a=this.isContextual(96);if(a&&this.recordAwaitIfAllowed()){this.next();var n=this.parseAwait(r);return t||this.checkExponentialAfterUnary(n),n}var s,o=this.match(34),i=this.startNode();if(s=this.state.type,nb[s]){i.operator=this.state.value,i.prefix=!0,this.match(72)&&this.expectPlugin("throwExpressions");var d=this.match(89);if(this.next(),i.argument=this.parseMaybeUnary(null,!0),this.checkExpressionErrors(e,!0),this.state.strict&&d){var c=i.argument;"Identifier"===c.type?this.raise(wh.StrictDelete,i):this.hasPropertyAsPrivateName(c)&&this.raise(wh.DeletePrivateField,i)}if(!o)return t||this.checkExponentialAfterUnary(i),this.finishNode(i,"UnaryExpression")}var l=this.parseUpdate(i,o,e);if(a){var u=this.state.type;if((this.hasPlugin("v8intrinsic")?ub(u):ub(u)&&!this.match(54))&&!this.isAmbiguousPrefixOrIdentifier())return this.raiseOverwrite(wh.AwaitNotInAsyncContext,r),this.parseAwait(r)}return l},r.parseUpdate=function(e,t,r){if(t){var a=e;return this.checkLVal(a.argument,this.finishNode(a,"UpdateExpression")),e}var n=this.state.startLoc,s=this.parseExprSubscripts(r);if(this.checkExpressionErrors(r,!1))return s;for(;gb(this.state.type)&&!this.canInsertSemicolon();){var o=this.startNodeAt(n);o.operator=this.state.value,o.prefix=!1,o.argument=s,this.next(),this.checkLVal(s,s=this.finishNode(o,"UpdateExpression"))}return s},r.parseExprSubscripts=function(e){var t=this.state.startLoc,r=this.state.potentialArrowAt,a=this.parseExprAtom(e);return this.shouldExitDescending(a,r)?a:this.parseSubscripts(a,t)},r.parseSubscripts=function(e,t,r){var a={optionalChainMember:!1,maybeAsyncArrow:this.atPossibleAsyncArrow(e),stop:!1};do{e=this.parseSubscript(e,t,r,a),a.maybeAsyncArrow=!1}while(!a.stop);return e},r.parseSubscript=function(e,t,r,a){var n=this.state.type;if(!r&&15===n)return this.parseBind(e,t,r,a);if(hb(n))return this.parseTaggedTemplateExpression(e,t,a);var s=!1;if(18===n){if(r&&(this.raise(wh.OptionalChainingNoNew,this.state.startLoc),40===this.lookaheadCharCode()))return this.stopParseSubscript(e,a);a.optionalChainMember=s=!0,this.next()}if(!r&&this.match(10))return this.parseCoverCallAndAsyncArrowHead(e,t,a,s);var o=this.eat(0);return o||s||this.eat(16)?this.parseMember(e,t,a,o,s):this.stopParseSubscript(e,a)},r.stopParseSubscript=function(e,t){return t.stop=!0,e},r.parseMember=function(e,t,r,a,n){var s=this.startNodeAt(t);return s.object=e,s.computed=a,a?(s.property=this.parseExpression(),this.expect(3)):this.match(139)?("Super"===e.type&&this.raise(wh.SuperPrivateField,t),this.classScope.usePrivateName(this.state.value,this.state.startLoc),s.property=this.parsePrivateName()):s.property=this.parseIdentifier(!0),r.optionalChainMember?(s.optional=n,this.finishNode(s,"OptionalMemberExpression")):this.finishNode(s,"MemberExpression")},r.parseBind=function(e,t,r,a){var n=this.startNodeAt(t);return n.object=e,this.next(),n.callee=this.parseNoCallExpr(),a.stop=!0,this.parseSubscripts(this.finishNode(n,"BindExpression"),t,r)},r.parseCoverCallAndAsyncArrowHead=function(e,t,r,a){var n=this.state.maybeInArrowParameters,s=null;this.state.maybeInArrowParameters=!0,this.next();var o=this.startNodeAt(t);o.callee=e;var i=r.maybeAsyncArrow,d=r.optionalChainMember;i&&(this.expressionScope.enter(new lv(2)),s=new gv),d&&(o.optional=a),o.arguments=a?this.parseCallExpressionArguments():this.parseCallExpressionArguments("Super"!==e.type,o,s);var c=this.finishCallExpression(o,d);return i&&this.shouldParseAsyncArrow()&&!a?(r.stop=!0,this.checkDestructuringPrivate(s),this.expressionScope.validateAsPattern(),this.expressionScope.exit(),c=this.parseAsyncArrowFromCallExpression(this.startNodeAt(t),c)):(i&&(this.checkExpressionErrors(s,!0),this.expressionScope.exit()),this.toReferencedArguments(c)),this.state.maybeInArrowParameters=n,c},r.toReferencedArguments=function(e,t){this.toReferencedListDeep(e.arguments,t)},r.parseTaggedTemplateExpression=function(e,t,r){var a=this.startNodeAt(t);return a.tag=e,a.quasi=this.parseTemplate(!0),r.optionalChainMember&&this.raise(wh.OptionalChainingNoTemplate,t),this.finishNode(a,"TaggedTemplateExpression")},r.atPossibleAsyncArrow=function(e){return"Identifier"===e.type&&"async"===e.name&&this.state.lastTokEndLoc.index===e.end&&!this.canInsertSemicolon()&&e.end-e.start===5&&this.offsetToSourcePos(e.start)===this.state.potentialArrowAt},r.finishCallExpression=function(e,t){if("Import"===e.callee.type)if(0===e.arguments.length||e.arguments.length>2)this.raise(wh.ImportCallArity,e);else for(var r=0,a=e.arguments;r1?((t=this.startNodeAt(i)).expressions=d,this.finishNode(t,"SequenceExpression"),this.resetEndLocation(t,p)):t=d[0],this.wrapParenthesis(r,t))},r.wrapParenthesis=function(e,t){if(!(this.optionFlags&Nh))return this.addExtra(t,"parenthesized",!0),this.addExtra(t,"parenStart",e.index),this.takeSurroundingComments(t,e.index,this.state.lastTokEndLoc.index),t;var r=this.startNodeAt(e);return r.expression=t,this.finishNode(r,"ParenthesizedExpression")},r.shouldParseArrow=function(e){return!this.canInsertSemicolon()},r.parseArrow=function(e){if(this.eat(19))return e},r.parseParenItem=function(e,t){return e},r.parseNewOrNewTarget=function(){var e=this.startNode();if(this.next(),this.match(16)){var t=this.createIdentifier(this.startNodeAtNode(e),"new");this.next();var r=this.parseMetaProperty(e,t,"target");return this.scope.allowNewTarget||this.raise(wh.UnexpectedNewTarget,r),r}return this.parseNew(e)},r.parseNew=function(e){if(this.parseNewCallee(e),this.eat(10)){var t=this.parseExprList(11);this.toReferencedList(t),e.arguments=t}else e.arguments=[];return this.finishNode(e,"NewExpression")},r.parseNewCallee=function(e){var t=this.match(83),r=this.parseNoCallExpr();e.callee=r,!t||"Import"!==r.type&&"ImportExpression"!==r.type||this.raise(wh.ImportCallNotNewExpression,r)},r.parseTemplateElement=function(e){var t=this.state,r=t.start,a=t.startLoc,n=t.end,s=t.value,o=r+1,i=this.startNodeAt(lh(a,1));null===s&&(e||this.raise(wh.InvalidEscapeSequenceTemplate,lh(this.state.firstInvalidTemplateEscapePos,1)));var d=this.match(24),c=d?-1:-2,l=n+c;i.value={raw:this.input.slice(o,l).replace(/\r\n?/g,"\n"),cooked:null===s?null:s.slice(1,c)},i.tail=d,this.next();var u=this.finishNode(i,"TemplateElement");return this.resetEndLocation(u,lh(this.state.lastTokEndLoc,c)),u},r.parseTemplate=function(e){for(var t=this.startNode(),r=this.parseTemplateElement(e),a=[r],n=[];!r.tail;)n.push(this.parseTemplateSubstitution()),this.readTemplateContinuation(),a.push(r=this.parseTemplateElement(e));return t.expressions=n,t.quasis=a,this.finishNode(t,"TemplateLiteral")},r.parseTemplateSubstitution=function(){return this.parseExpression()},r.parseObjectLike=function(e,t,r,a){r&&this.expectPlugin("recordAndTuple");var n=this.state.inFSharpPipelineDirectBody;this.state.inFSharpPipelineDirectBody=!1;var s=!1,o=!0,i=this.startNode();for(i.properties=[],this.next();!this.match(e);){if(o)o=!1;else if(this.expect(12),this.match(e)){this.addTrailingCommaExtraToNode(i);break}var d=void 0;t?d=this.parseBindingProperty():(d=this.parsePropertyDefinition(a),s=this.checkProto(d,r,s,a)),r&&!this.isObjectProperty(d)&&"SpreadElement"!==d.type&&this.raise(wh.InvalidRecordProperty,d),d.shorthand&&this.addExtra(d,"shorthand",!0),i.properties.push(d)}this.next(),this.state.inFSharpPipelineDirectBody=n;var c="ObjectExpression";return t?c="ObjectPattern":r&&(c="RecordExpression"),this.finishNode(i,c)},r.addTrailingCommaExtraToNode=function(e){this.addExtra(e,"trailingComma",this.state.lastTokStartLoc.index),this.addExtra(e,"trailingCommaLoc",this.state.lastTokStartLoc,!1)},r.maybeAsyncOrAccessorProp=function(e){return!e.computed&&"Identifier"===e.key.type&&(this.isLiteralPropertyName()||this.match(0)||this.match(55))},r.parsePropertyDefinition=function(e){var t=[];if(this.match(26))for(this.hasPlugin("decorators")&&this.raise(wh.UnsupportedPropertyDecorator,this.state.startLoc);this.match(26);)t.push(this.parseDecorator());var r,a=this.startNode(),n=!1,s=!1;if(this.match(21))return t.length&&this.unexpected(),this.parseSpread();t.length&&(a.decorators=t,t=[]),a.method=!1,e&&(r=this.state.startLoc);var o=this.eat(55);this.parsePropertyNamePrefixOperator(a);var i=this.state.containsEsc;if(this.parsePropertyName(a,e),!o&&!i&&this.maybeAsyncOrAccessorProp(a)){var d=a.key,c=d.name;"async"!==c||this.hasPrecedingLineBreak()||(n=!0,this.resetPreviousNodeTrailingComments(d),o=this.eat(55),this.parsePropertyName(a)),"get"!==c&&"set"!==c||(s=!0,this.resetPreviousNodeTrailingComments(d),a.kind=c,this.match(55)&&(o=!0,this.raise(wh.AccessorIsGenerator,this.state.curPosition(),{kind:c}),this.next()),this.parsePropertyName(a))}return this.parseObjPropValue(a,r,o,n,!1,s,e)},r.getGetterSetterExpectedParamCount=function(e){return"get"===e.kind?0:1},r.getObjectOrClassMethodParams=function(e){return e.params},r.checkGetterSetterParams=function(e){var t,r=this.getGetterSetterExpectedParamCount(e),a=this.getObjectOrClassMethodParams(e);a.length!==r&&this.raise("get"===e.kind?wh.BadGetterArity:wh.BadSetterArity,e),"set"===e.kind&&"RestElement"===(null==(t=a[a.length-1])?void 0:t.type)&&this.raise(wh.BadSetterRestParameter,e)},r.parseObjectMethod=function(e,t,r,a,n){if(n){var s=this.parseMethod(e,t,!1,!1,!1,"ObjectMethod");return this.checkGetterSetterParams(s),s}if(r||t||this.match(10))return a&&this.unexpected(),e.kind="method",e.method=!0,this.parseMethod(e,t,r,!1,!1,"ObjectMethod")},r.parseObjectProperty=function(e,t,r,a){if(e.shorthand=!1,this.eat(14))return e.value=r?this.parseMaybeDefault(this.state.startLoc):this.parseMaybeAssignAllowInOrVoidPattern(8,a),this.finishObjectProperty(e);if(!e.computed&&"Identifier"===e.key.type){if(this.checkReservedWord(e.key.name,e.key.loc.start,!0,!1),r)e.value=this.parseMaybeDefault(t,this.cloneIdentifier(e.key));else if(this.match(29)){var n=this.state.startLoc;null!=a?null===a.shorthandAssignLoc&&(a.shorthandAssignLoc=n):this.raise(wh.InvalidCoverInitializedName,n),e.value=this.parseMaybeDefault(t,this.cloneIdentifier(e.key))}else e.value=this.cloneIdentifier(e.key);return e.shorthand=!0,this.finishObjectProperty(e)}},r.finishObjectProperty=function(e){return this.finishNode(e,"ObjectProperty")},r.parseObjPropValue=function(e,t,r,a,n,s,o){var i=this.parseObjectMethod(e,r,a,n,s)||this.parseObjectProperty(e,t,n,o);return i||this.unexpected(),i},r.parsePropertyName=function(e,t){if(this.eat(0))e.computed=!0,e.key=this.parseMaybeAssignAllowIn(),this.expect(3);else{var r,a=this.state,n=a.type,s=a.value;if(cb(n))r=this.parseIdentifier(!0);else switch(n){case 135:r=this.parseNumericLiteral(s);break;case 134:r=this.parseStringLiteral(s);break;case 136:r=this.parseBigIntLiteral(s);break;case 139:var o=this.state.startLoc;null!=t?null===t.privateKeyLoc&&(t.privateKeyLoc=o):this.raise(wh.UnexpectedPrivateField,o),r=this.parsePrivateName();break;default:if(137===n){r=this.parseDecimalLiteral(s);break}this.unexpected()}e.key=r,139!==n&&(e.computed=!1)}},r.initFunction=function(e,t){e.id=null,e.generator=!1,e.async=t},r.parseMethod=function(e,t,r,a,n,s,o){void 0===o&&(o=!1),this.initFunction(e,r),e.generator=t,this.scope.enter(Db|Tb|(o?Nb:0)|(n?Pb:0)),this.prodParam.enter(Xx(r,e.generator)),this.parseFunctionParams(e,a);var i=this.parseFunctionBodyAndFinish(e,s,!0);return this.prodParam.exit(),this.scope.exit(),i},r.parseArrayLike=function(e,t,r,a){r&&this.expectPlugin("recordAndTuple");var n=this.state.inFSharpPipelineDirectBody;this.state.inFSharpPipelineDirectBody=!1;var s=this.startNode();return this.next(),s.elements=this.parseExprList(e,!r,a,s),this.state.inFSharpPipelineDirectBody=n,this.finishNode(s,r?"TupleExpression":"ArrayExpression")},r.parseArrowExpression=function(e,t,r,a){this.scope.enter(Db|Eb);var n=Xx(r,!1);!this.match(5)&&this.prodParam.hasIn&&(n|=Kx),this.prodParam.enter(n),this.initFunction(e,r);var s=this.state.maybeInArrowParameters;return t&&(this.state.maybeInArrowParameters=!0,this.setArrowFunctionParameters(e,t,a)),this.state.maybeInArrowParameters=!1,this.parseFunctionBody(e,!0),this.prodParam.exit(),this.scope.exit(),this.state.maybeInArrowParameters=s,this.finishNode(e,"ArrowFunctionExpression")},r.setArrowFunctionParameters=function(e,t,r){this.toAssignableList(t,r,!1),e.params=t},r.parseFunctionBodyAndFinish=function(e,t,r){return void 0===r&&(r=!1),this.parseFunctionBody(e,!1,r),this.finishNode(e,t)},r.parseFunctionBody=function(e,t,r){var a=this;void 0===r&&(r=!1);var n=t&&!this.match(5);if(this.expressionScope.enter(pv()),n)e.body=this.parseMaybeAssign(),this.checkParams(e,!1,t,!1);else{var s=this.state.strict,o=this.state.labels;this.state.labels=[],this.prodParam.enter(this.prodParam.currentFlags()|Hx),e.body=this.parseBlock(!0,!1,function(n){var o=!a.isSimpleParamList(e.params);n&&o&&a.raise(wh.IllegalLanguageModeDirective,"method"!==e.kind&&"constructor"!==e.kind||!e.key?e:e.key.loc.end);var i=!s&&a.state.strict;a.checkParams(e,!(a.state.strict||t||r||o),t,i),a.state.strict&&e.id&&a.checkIdentifier(e.id,nx,i)}),this.prodParam.exit(),this.state.labels=o}this.expressionScope.exit()},r.isSimpleParameter=function(e){return"Identifier"===e.type},r.isSimpleParamList=function(e){for(var t=0,r=e.length;t10)&&function(e){return xb.has(e)}(e))if(r&&Qr(e))this.raise(wh.UnexpectedKeyword,t,{keyword:e});else if((this.state.strict?a?$r:Jr:Xr)(e,this.inModule))this.raise(wh.UnexpectedReservedWord,t,{reservedWord:e});else if("yield"===e){if(this.prodParam.hasYield)return void this.raise(wh.YieldBindingIdentifier,t)}else if("await"===e){if(this.prodParam.hasAwait)return void this.raise(wh.AwaitBindingIdentifier,t);if(this.scope.inStaticBlock)return void this.raise(wh.AwaitBindingIdentifierInStaticBlock,t);this.expressionScope.recordAsyncArrowParametersError(t)}else if("arguments"===e&&this.scope.inClassAndNotInNonArrowFunction)return void this.raise(wh.ArgumentsInClass,t)},r.recordAwaitIfAllowed=function(){var e=this.prodParam.hasAwait;return e&&!this.scope.inFunction&&(this.state.hasTopLevelAwait=!0),e},r.parseAwait=function(e){var t=this.startNodeAt(e);return this.expressionScope.recordParameterInitializerError(wh.AwaitExpressionFormalParameter,t),this.eat(55)&&this.raise(wh.ObsoleteAwaitStar,t),this.scope.inFunction||this.optionFlags&Eh||(this.isAmbiguousPrefixOrIdentifier()?this.ambiguousScriptDifferentAst=!0:this.sawUnambiguousESM=!0),this.state.soloAwait||(t.argument=this.parseMaybeUnary(null,!0)),this.finishNode(t,"AwaitExpression")},r.isAmbiguousPrefixOrIdentifier=function(){if(this.hasPrecedingLineBreak())return!0;var e=this.state.type;return 53===e||10===e||0===e||hb(e)||102===e&&!this.state.containsEsc||138===e||56===e||this.hasPlugin("v8intrinsic")&&54===e},r.parseYield=function(e){var t=this.startNodeAt(e);this.expressionScope.recordParameterInitializerError(wh.YieldInParameter,t);var r=!1,a=null;if(!this.hasPrecedingLineBreak())switch(r=this.eat(55),this.state.type){case 13:case 140:case 8:case 11:case 3:case 9:case 14:case 12:if(!r)break;default:a=this.parseMaybeAssign()}return t.delegate=r,t.argument=a,this.finishNode(t,"YieldExpression")},r.parseImportCall=function(e){if(this.next(),e.source=this.parseMaybeAssignAllowIn(),e.options=null,this.eat(12))if(this.match(11))this.addTrailingCommaExtraToNode(e.source);else if(e.options=this.parseMaybeAssignAllowIn(),this.eat(12)&&(this.addTrailingCommaExtraToNode(e.options),!this.match(11))){do{this.parseMaybeAssignAllowIn()}while(this.eat(12)&&!this.match(11));this.raise(wh.ImportCallArity,e)}return this.expect(11),this.finishNode(e,"ImportExpression")},r.checkPipelineAtInfixOperator=function(e,t){this.hasPlugin(["pipelineOperator",{proposal:"smart"}])&&"SequenceExpression"===e.type&&this.raise(wh.PipelineHeadSequenceExpression,t)},r.parseSmartPipelineBodyInStyle=function(e,t){if(this.isSimpleReference(e)){var r=this.startNodeAt(t);return r.callee=e,this.finishNode(r,"PipelineBareFunction")}var a=this.startNodeAt(t);return this.checkSmartPipeTopicBodyEarlyErrors(t),a.expression=e,this.finishNode(a,"PipelineTopicExpression")},r.isSimpleReference=function(e){switch(e.type){case"MemberExpression":return!e.computed&&this.isSimpleReference(e.object);case"Identifier":return!0;default:return!1}},r.checkSmartPipeTopicBodyEarlyErrors=function(e){if(this.match(19))throw this.raise(wh.PipelineBodyNoArrow,this.state.startLoc);this.topicReferenceWasUsedInCurrentContext()||this.raise(wh.PipelineTopicUnused,e)},r.withTopicBindingContext=function(e){var t=this.state.topicContext;this.state.topicContext={maxNumOfResolvableTopics:1,maxTopicIndex:null};try{return e()}finally{this.state.topicContext=t}},r.withSmartMixTopicForbiddingContext=function(e){if(!this.hasPlugin(["pipelineOperator",{proposal:"smart"}]))return e();var t=this.state.topicContext;this.state.topicContext={maxNumOfResolvableTopics:0,maxTopicIndex:null};try{return e()}finally{this.state.topicContext=t}},r.withSoloAwaitPermittingContext=function(e){var t=this.state.soloAwait;this.state.soloAwait=!0;try{return e()}finally{this.state.soloAwait=t}},r.allowInAnd=function(e){var t=this.prodParam.currentFlags();if(Kx&~t){this.prodParam.enter(t|Kx);try{return e()}finally{this.prodParam.exit()}}return e()},r.disallowInAnd=function(e){var t=this.prodParam.currentFlags();if(Kx&t){this.prodParam.enter(t&~Kx);try{return e()}finally{this.prodParam.exit()}}return e()},r.registerTopicReference=function(){this.state.topicContext.maxTopicIndex=0},r.topicReferenceIsAllowedInCurrentContext=function(){return this.state.topicContext.maxNumOfResolvableTopics>=1},r.topicReferenceWasUsedInCurrentContext=function(){return null!=this.state.topicContext.maxTopicIndex&&this.state.topicContext.maxTopicIndex>=0},r.parseFSharpPipelineBody=function(e){var t=this.state.startLoc;this.state.potentialArrowAt=this.state.start;var r=this.state.inFSharpPipelineDirectBody;this.state.inFSharpPipelineDirectBody=!0;var a=this.parseExprOp(this.parseMaybeUnaryOrPrivate(),t,e);return this.state.inFSharpPipelineDirectBody=r,a},r.parseModuleExpression=function(){this.expectPlugin("moduleBlocks");var e=this.startNode();this.next(),this.match(5)||this.unexpected(null,5);var t=this.startNodeAt(this.state.endLoc);this.next();var r=this.initializeScopes(!0);this.enterInitialScopes();try{e.body=this.parseProgram(t,8,"module")}finally{r()}return this.finishNode(e,"ModuleExpression")},r.parseVoidPattern=function(e){this.expectPlugin("discardBinding");var t=this.startNode();return null!=e&&(e.voidPatternLoc=this.state.startLoc),this.next(),this.finishNode(t,"VoidPattern")},r.parseMaybeAssignAllowInOrVoidPattern=function(e,t,r){if(null!=t&&this.match(88)){var a=this.lookaheadCharCode();if(44===a||a===(3===e?93:8===e?125:41)||61===a)return this.parseMaybeDefault(this.state.startLoc,this.parseVoidPattern(t))}return this.parseMaybeAssignAllowIn(t,r)},r.parsePropertyNamePrefixOperator=function(e){},o(t)}(wv),Gv={kind:ev},Wv={kind:tv},Vv=0,Hv=1,Kv=2,zv=4,Xv=8,Jv=0,Yv=1,$v=2,Qv=4,Zv=8,eR=/(?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/,tR=new RegExp("in(?:stanceof)?","y");var rR=function(e){function t(){return e.apply(this,arguments)||this}c(t,e);var r=t.prototype;return r.parseTopLevel=function(e,t){return e.program=this.parseProgram(t,140,"module"===this.options.sourceType?"module":"script"),e.comments=this.comments,this.optionFlags&Ih&&(e.tokens=function(e,t,r){for(var a=0;a0)for(var a=0,n=Array.from(this.scope.undefinedExports);a=90&&o<=92?ev:this.match(71)?tv:null,d=this.state.labels.length-1;d>=0;d--){var c=this.state.labels[d];if(c.statementStart!==e.start)break;c.statementStart=this.sourceToOffsetPos(this.state.start),c.kind=i}return this.state.labels.push({name:t,kind:i,statementStart:this.sourceToOffsetPos(this.state.start)}),e.body=a&Zv?this.parseStatementOrSloppyAnnexBFunctionDeclaration(!0):this.parseStatement(),this.state.labels.pop(),e.label=r,this.finishNode(e,"LabeledStatement")},r.parseExpressionStatement=function(e,t,r){return e.expression=t,this.semicolon(),this.finishNode(e,"ExpressionStatement")},r.parseBlock=function(e,t,r){void 0===e&&(e=!1),void 0===t&&(t=!0);var a=this.startNode();return e&&this.state.strictErrors.clear(),this.expect(5),t&&this.scope.enter(Rb),this.parseBlockBody(a,e,!1,8,r),t&&this.scope.exit(),this.finishNode(a,"BlockStatement")},r.isValidDirective=function(e){return"ExpressionStatement"===e.type&&"StringLiteral"===e.expression.type&&!e.expression.extra.parenthesized},r.parseBlockBody=function(e,t,r,a,n){var s=e.body=[],o=e.directives=[];this.parseBlockOrModuleBlockBody(s,t?o:void 0,r,a,n)},r.parseBlockOrModuleBlockBody=function(e,t,r,a,n){for(var s=this.state.strict,o=!1,i=!1;!this.match(a);){var d=r?this.parseModuleItem():this.parseStatementListItem();if(t&&!i){if(this.isValidDirective(d)){var c=this.stmtToDirective(d);t.push(c),o||"use strict"!==c.value.value||(o=!0,this.setStrict(!0));continue}i=!0,this.state.strictErrors.clear()}e.push(d)}null==n||n.call(this,o),s||this.setStrict(!1),this.next()},r.parseFor=function(e,t){var r=this;return e.init=t,this.semicolon(!1),e.test=this.match(13)?null:this.parseExpression(),this.semicolon(!1),e.update=this.match(11)?null:this.parseExpression(),this.expect(11),e.body=this.withSmartMixTopicForbiddingContext(function(){return r.parseStatement()}),this.scope.exit(),this.state.labels.pop(),this.finishNode(e,"ForStatement")},r.parseForIn=function(e,t,r){var a=this,n=this.match(58);return this.next(),n?null!==r&&this.unexpected(r):e.await=null!==r,"VariableDeclaration"!==t.type||null==t.declarations[0].init||n&&this.options.annexB&&!this.state.strict&&"var"===t.kind&&"Identifier"===t.declarations[0].id.type||this.raise(wh.ForInOfLoopInitializer,t,{type:n?"ForInStatement":"ForOfStatement"}),"AssignmentPattern"===t.type&&this.raise(wh.InvalidLhs,t,{ancestor:{type:"ForStatement"}}),e.left=t,e.right=n?this.parseExpression():this.parseMaybeAssignAllowIn(),this.expect(11),e.body=this.withSmartMixTopicForbiddingContext(function(){return a.parseStatement()}),this.scope.exit(),this.state.labels.pop(),this.finishNode(e,n?"ForInStatement":"ForOfStatement")},r.parseVar=function(e,t,r,a){void 0===a&&(a=!1);var n=e.declarations=[];for(e.kind=r;;){var s=this.startNode();if(this.parseVarId(s,r),s.init=this.eat(29)?t?this.parseMaybeAssignDisallowIn():this.parseMaybeAssignAllowIn():null,null!==s.init||a||("Identifier"===s.id.type||t&&(this.match(58)||this.isContextual(102))?"const"!==r&&"using"!==r&&"await using"!==r||this.match(58)||this.isContextual(102)||this.raise(wh.DeclarationMissingInitializer,this.state.lastTokEndLoc,{kind:r}):this.raise(wh.DeclarationMissingInitializer,this.state.lastTokEndLoc,{kind:"destructuring"})),n.push(this.finishNode(s,"VariableDeclarator")),!this.eat(12))break}return e},r.parseVarId=function(e,t){var r=this.parseBindingAtom();"using"===t||"await using"===t?"ArrayPattern"!==r.type&&"ObjectPattern"!==r.type||this.raise(wh.UsingDeclarationHasBindingPattern,r.loc.start):"VoidPattern"===r.type&&this.raise(wh.UnexpectedVoidPattern,r.loc.start),this.checkLVal(r,{type:"VariableDeclarator"},"var"===t?$b:Jb),e.id=r},r.parseAsyncFunctionExpression=function(e){return this.parseFunction(e,Xv)},r.parseFunction=function(e,t){var r=this;void 0===t&&(t=Vv);var a=t&Kv,n=!!(t&Hv),s=n&&!(t&zv),o=!!(t&Xv);this.initFunction(e,o),this.match(55)&&(a&&this.raise(wh.GeneratorInSingleStatementContext,this.state.startLoc),this.next(),e.generator=!0),n&&(e.id=this.parseFunctionId(s));var i=this.state.maybeInArrowParameters;return this.state.maybeInArrowParameters=!1,this.scope.enter(Db),this.prodParam.enter(Xx(o,e.generator)),n||(e.id=this.parseFunctionId()),this.parseFunctionParams(e,!1),this.withSmartMixTopicForbiddingContext(function(){r.parseFunctionBodyAndFinish(e,n?"FunctionDeclaration":"FunctionExpression")}),this.prodParam.exit(),this.scope.exit(),n&&!a&&this.registerFunctionStatementId(e),this.state.maybeInArrowParameters=i,e},r.parseFunctionId=function(e){return e||db(this.state.type)?this.parseIdentifier():null},r.parseFunctionParams=function(e,t){this.expect(10),this.expressionScope.enter(new cv(3)),e.params=this.parseBindingList(11,41,Rv|(t?jv:0)),this.expressionScope.exit()},r.registerFunctionStatementId=function(e){e.id&&this.scope.declareName(e.id.name,!this.options.annexB||this.state.strict||e.generator||e.async?this.scope.treatFunctionsAsVar?$b:Jb:Qb,e.id.loc.start)},r.parseClass=function(e,t,r){this.next();var a=this.state.strict;return this.state.strict=!0,this.parseClassId(e,t,r),this.parseClassSuper(e),e.body=this.parseClassBody(!!e.superClass,a),this.finishNode(e,t?"ClassDeclaration":"ClassExpression")},r.isClassProperty=function(){return this.match(29)||this.match(13)||this.match(8)},r.isClassMethod=function(){return this.match(10)},r.nameIsConstructor=function(e){return"Identifier"===e.type&&"constructor"===e.name||"StringLiteral"===e.type&&"constructor"===e.value},r.isNonstaticConstructor=function(e){return!e.computed&&!e.static&&this.nameIsConstructor(e.key)},r.parseClassBody=function(e,t){var r=this;this.classScope.enter();var a={hadConstructor:!1,hadSuperClass:e},n=[],s=this.startNode();if(s.body=[],this.expect(5),this.withSmartMixTopicForbiddingContext(function(){for(;!r.match(8);)if(r.eat(13)){if(n.length>0)throw r.raise(wh.DecoratorSemicolon,r.state.lastTokEndLoc)}else if(r.match(26))n.push(r.parseDecorator());else{var e=r.startNode();n.length&&(e.decorators=n,r.resetStartLocationFromNode(e,n[0]),n=[]),r.parseClassMember(s,e,a),"constructor"===e.kind&&e.decorators&&e.decorators.length>0&&r.raise(wh.DecoratorConstructor,e)}}),this.state.strict=t,this.next(),n.length)throw this.raise(wh.TrailingDecorator,this.state.startLoc);return this.classScope.exit(),this.finishNode(s,"ClassBody")},r.parseClassMemberFromModifier=function(e,t){var r=this.parseIdentifier(!0);if(this.isClassMethod()){var a=t;return a.kind="method",a.computed=!1,a.key=r,a.static=!1,this.pushClassMethod(e,a,!1,!1,!1,!1),!0}if(this.isClassProperty()){var n=t;return n.computed=!1,n.key=r,n.static=!1,e.body.push(this.parseClassProperty(n)),!0}return this.resetPreviousNodeTrailingComments(r),!1},r.parseClassMember=function(e,t,r){var a=this.isContextual(106);if(a){if(this.parseClassMemberFromModifier(e,t))return;if(this.eat(5))return void this.parseClassStaticBlock(e,t)}this.parseClassMemberWithIsStatic(e,t,r,a)},r.parseClassMemberWithIsStatic=function(e,t,r,a){var n=t,s=t,o=t,i=t,d=t,c=n,l=n;if(t.static=a,this.parsePropertyNamePrefixOperator(t),this.eat(55)){c.kind="method";var u=this.match(139);return this.parseClassElementName(c),this.parsePostMemberNameModifiers(c),u?void this.pushClassPrivateMethod(e,s,!0,!1):(this.isNonstaticConstructor(n)&&this.raise(wh.ConstructorIsGenerator,n.key),void this.pushClassMethod(e,n,!0,!1,!1,!1))}var p=!this.state.containsEsc&&db(this.state.type),f=this.parseClassElementName(t),g=p?f.name:null,y=this.isPrivateName(f),m=this.state.startLoc;if(this.parsePostMemberNameModifiers(l),this.isClassMethod()){if(c.kind="method",y)return void this.pushClassPrivateMethod(e,s,!1,!1);var h=this.isNonstaticConstructor(n),b=!1;h&&(n.kind="constructor",r.hadConstructor&&!this.hasPlugin("typescript")&&this.raise(wh.DuplicateConstructor,f),h&&this.hasPlugin("typescript")&&t.override&&this.raise(wh.OverrideOnConstructor,f),r.hadConstructor=!0,b=r.hadSuperClass),this.pushClassMethod(e,n,!1,!1,h,b)}else if(this.isClassProperty())y?this.pushClassPrivateProperty(e,i):this.pushClassProperty(e,o);else if("async"!==g||this.isLineTerminator())if("get"!==g&&"set"!==g||this.match(55)&&this.isLineTerminator())if("accessor"!==g||this.isLineTerminator())this.isLineTerminator()?y?this.pushClassPrivateProperty(e,i):this.pushClassProperty(e,o):this.unexpected();else{this.expectPlugin("decoratorAutoAccessors"),this.resetPreviousNodeTrailingComments(f);var x=this.match(139);this.parseClassElementName(o),this.pushClassAccessorProperty(e,d,x)}else{this.resetPreviousNodeTrailingComments(f),c.kind=g;var v=this.match(139);this.parseClassElementName(n),v?this.pushClassPrivateMethod(e,s,!1,!1):(this.isNonstaticConstructor(n)&&this.raise(wh.ConstructorIsAccessor,n.key),this.pushClassMethod(e,n,!1,!1,!1,!1)),this.checkGetterSetterParams(n)}else{this.resetPreviousNodeTrailingComments(f);var R=this.eat(55);l.optional&&this.unexpected(m),c.kind="method";var j=this.match(139);this.parseClassElementName(c),this.parsePostMemberNameModifiers(l),j?this.pushClassPrivateMethod(e,s,R,!0):(this.isNonstaticConstructor(n)&&this.raise(wh.ConstructorIsAsync,n.key),this.pushClassMethod(e,n,R,!0,!1,!1))}},r.parseClassElementName=function(e){var t=this.state,r=t.type,a=t.value;if(132!==r&&134!==r||!e.static||"prototype"!==a||this.raise(wh.StaticPrototype,this.state.startLoc),139===r){"constructor"===a&&this.raise(wh.ConstructorClassPrivateField,this.state.startLoc);var n=this.parsePrivateName();return e.key=n,n}return this.parsePropertyName(e),e.key},r.parseClassStaticBlock=function(e,t){var r;this.scope.enter(Nb|kb|Tb);var a=this.state.labels;this.state.labels=[],this.prodParam.enter(Gx);var n=t.body=[];this.parseBlockOrModuleBlockBody(n,void 0,!1,8),this.prodParam.exit(),this.scope.exit(),this.state.labels=a,e.body.push(this.finishNode(t,"StaticBlock")),null!=(r=t.decorators)&&r.length&&this.raise(wh.DecoratorStaticBlock,t)},r.pushClassProperty=function(e,t){!t.computed&&this.nameIsConstructor(t.key)&&this.raise(wh.ConstructorClassField,t.key),e.body.push(this.parseClassProperty(t))},r.pushClassPrivateProperty=function(e,t){var r=this.parseClassPrivateProperty(t);e.body.push(r),this.classScope.declarePrivateName(this.getPrivateNameSV(r.key),lx,r.key.loc.start)},r.pushClassAccessorProperty=function(e,t,r){r||t.computed||!this.nameIsConstructor(t.key)||this.raise(wh.ConstructorClassField,t.key);var a=this.parseClassAccessorProperty(t);e.body.push(a),r&&this.classScope.declarePrivateName(this.getPrivateNameSV(a.key),lx,a.key.loc.start)},r.pushClassMethod=function(e,t,r,a,n,s){e.body.push(this.parseMethod(t,r,a,n,s,"ClassMethod",!0))},r.pushClassPrivateMethod=function(e,t,r,a){var n=this.parseMethod(t,r,a,!1,!1,"ClassPrivateMethod",!0);e.body.push(n);var s="get"===n.kind?n.static?fx:yx:"set"===n.kind?n.static?gx:mx:lx;this.declareClassPrivateMethodInScope(n,s)},r.declareClassPrivateMethodInScope=function(e,t){this.classScope.declarePrivateName(this.getPrivateNameSV(e.key),t,e.key.loc.start)},r.parsePostMemberNameModifiers=function(e){},r.parseClassPrivateProperty=function(e){return this.parseInitializer(e),this.semicolon(),this.finishNode(e,"ClassPrivateProperty")},r.parseClassProperty=function(e){return this.parseInitializer(e),this.semicolon(),this.finishNode(e,"ClassProperty")},r.parseClassAccessorProperty=function(e){return this.parseInitializer(e),this.semicolon(),this.finishNode(e,"ClassAccessorProperty")},r.parseInitializer=function(e){this.scope.enter(Nb|Tb),this.expressionScope.enter(pv()),this.prodParam.enter(Gx),e.value=this.eat(29)?this.parseMaybeAssignAllowIn():null,this.expressionScope.exit(),this.prodParam.exit(),this.scope.exit()},r.parseClassId=function(e,t,r,a){if(void 0===a&&(a=Xb),db(this.state.type))e.id=this.parseIdentifier(),t&&this.declareNameFromIdentifier(e.id,a);else{if(!r&&t)throw this.raise(wh.MissingClassName,this.state.startLoc);e.id=null}},r.parseClassSuper=function(e){e.superClass=this.eat(81)?this.parseExprSubscripts():null},r.parseExport=function(e,t){var r=this.parseMaybeImportPhase(e,!0),a=this.maybeParseExportDefaultSpecifier(e,r),n=!a||this.eat(12),s=n&&this.eatExportStar(e),o=s&&this.maybeParseExportNamespaceSpecifier(e),i=n&&(!o||this.eat(12)),d=a||s;if(s&&!o){if(a&&this.unexpected(),t)throw this.raise(wh.UnsupportedDecoratorExport,e);return this.parseExportFrom(e,!0),this.sawUnambiguousESM=!0,this.finishNode(e,"ExportAllDeclaration")}var c,l=this.maybeParseExportNamedSpecifiers(e);if(a&&n&&!s&&!l&&this.unexpected(null,5),o&&i&&this.unexpected(null,98),d||l){if(c=!1,t)throw this.raise(wh.UnsupportedDecoratorExport,e);this.parseExportFrom(e,d)}else c=this.maybeParseExportDeclaration(e);if(d||l||c){var u,p=e;if(this.checkExport(p,!0,!1,!!p.source),"ClassDeclaration"===(null==(u=p.declaration)?void 0:u.type))this.maybeTakeDecorators(t,p.declaration,p);else if(t)throw this.raise(wh.UnsupportedDecoratorExport,e);return this.sawUnambiguousESM=!0,this.finishNode(p,"ExportNamedDeclaration")}if(this.eat(65)){var f=e,g=this.parseExportDefaultExpression();if(f.declaration=g,"ClassDeclaration"===g.type)this.maybeTakeDecorators(t,g,f);else if(t)throw this.raise(wh.UnsupportedDecoratorExport,e);return this.checkExport(f,!0,!0),this.sawUnambiguousESM=!0,this.finishNode(f,"ExportDefaultDeclaration")}this.unexpected(null,5)},r.eatExportStar=function(e){return this.eat(55)},r.maybeParseExportDefaultSpecifier=function(e,t){if(t||this.isExportDefaultSpecifier()){this.expectPlugin("exportDefaultFrom",null==t?void 0:t.loc.start);var r=t||this.parseIdentifier(!0),a=this.startNodeAtNode(r);return a.exported=r,e.specifiers=[this.finishNode(a,"ExportDefaultSpecifier")],!0}return!1},r.maybeParseExportNamespaceSpecifier=function(e){if(this.isContextual(93)){var t;null!=(t=e).specifiers||(t.specifiers=[]);var r=this.startNodeAt(this.state.lastTokStartLoc);return this.next(),r.exported=this.parseModuleExportName(),e.specifiers.push(this.finishNode(r,"ExportNamespaceSpecifier")),!0}return!1},r.maybeParseExportNamedSpecifiers=function(e){if(this.match(5)){var t,r=e;r.specifiers||(r.specifiers=[]);var a="type"===r.exportKind;return(t=r.specifiers).push.apply(t,this.parseExportSpecifiers(a)),r.source=null,this.hasPlugin("importAssertions")?r.assertions=[]:r.attributes=[],r.declaration=null,!0}return!1},r.maybeParseExportDeclaration=function(e){return!!this.shouldParseExportDeclaration()&&(e.specifiers=[],e.source=null,this.hasPlugin("importAssertions")?e.assertions=[]:e.attributes=[],e.declaration=this.parseExportDeclaration(e),!0)},r.isAsyncFunction=function(){if(!this.isContextual(95))return!1;var e=this.nextTokenInLineStart();return this.isUnparsedContextual(e,"function")},r.parseExportDefaultExpression=function(){var e=this.startNode();if(this.match(68))return this.next(),this.parseFunction(e,Hv|zv);if(this.isAsyncFunction())return this.next(),this.next(),this.parseFunction(e,Hv|zv|Xv);if(this.match(80))return this.parseClass(e,!0,!0);if(this.match(26))return this.hasPlugin("decorators")&&!0===this.getPluginOption("decorators","decoratorsBeforeExport")&&this.raise(wh.DecoratorBeforeExport,this.state.startLoc),this.parseClass(this.maybeTakeDecorators(this.parseDecorators(!1),this.startNode()),!0,!0);if(this.match(75)||this.match(74)||this.isLet()||this.isUsing()||this.isAwaitUsing())throw this.raise(wh.UnsupportedDefaultExport,this.state.startLoc);var t=this.parseMaybeAssignAllowIn();return this.semicolon(),t},r.parseExportDeclaration=function(e){return this.match(80)?this.parseClass(this.startNode(),!0,!1):this.parseStatementListItem()},r.isExportDefaultSpecifier=function(){var e=this.state.type;if(db(e)){if(95===e&&!this.state.containsEsc||100===e)return!1;if((130===e||129===e)&&!this.state.containsEsc){var t=this.nextTokenStart(),r=this.input.charCodeAt(t);if(123===r||this.chStartsBindingIdentifier(r,t)&&!this.input.startsWith("from",t))return this.expectOnePlugin(["flow","typescript"]),!1}}else if(!this.match(65))return!1;var a=this.nextTokenStart(),n=this.isUnparsedContextual(a,"from");if(44===this.input.charCodeAt(a)||db(this.state.type)&&n)return!0;if(this.match(65)&&n){var s=this.input.charCodeAt(this.nextTokenStartSince(a+4));return 34===s||39===s}return!1},r.parseExportFrom=function(e,t){this.eatContextual(98)?(e.source=this.parseImportSource(),this.checkExport(e),this.maybeParseImportAttributes(e),this.checkJSONModuleImport(e)):t&&this.unexpected(),this.semicolon()},r.shouldParseExportDeclaration=function(){var e=this.state.type;return 26===e&&(this.expectOnePlugin(["decorators","decorators-legacy"]),this.hasPlugin("decorators"))?(!0===this.getPluginOption("decorators","decoratorsBeforeExport")&&this.raise(wh.DecoratorBeforeExport,this.state.startLoc),!0):this.isUsing()||this.isAwaitUsing()?(this.raise(wh.UsingDeclarationExport,this.state.startLoc),!0):74===e||75===e||68===e||80===e||this.isLet()||this.isAsyncFunction()},r.checkExport=function(e,t,r,a){var n;if(t)if(r){if(this.checkDuplicateExports(e,"default"),this.hasPlugin("exportDefaultFrom")){var s,o=e.declaration;"Identifier"!==o.type||"from"!==o.name||o.end-o.start!==4||null!=(s=o.extra)&&s.parenthesized||this.raise(wh.ExportDefaultFromAsIdentifier,o)}}else if(null!=(n=e.specifiers)&&n.length)for(var i=0,d=e.specifiers;i0&&this.raise(wh.ImportReflectionHasAssertion,t[0].loc.start)}},r.checkJSONModuleImport=function(e){if(this.isJSONModuleImport(e)&&"ExportAllDeclaration"!==e.type){var t=e.specifiers;if(null!=t){var r=t.find(function(e){var t;if("ExportSpecifier"===e.type?t=e.local:"ImportSpecifier"===e.type&&(t=e.imported),void 0!==t)return"Identifier"===t.type?"default"!==t.name:"default"!==t.value});void 0!==r&&this.raise(wh.ImportJSONBindingNotDefault,r.loc.start)}}},r.isPotentialImportPhase=function(e){return!e&&(this.isContextual(105)||this.isContextual(97)||this.isContextual(127))},r.applyImportPhase=function(e,t,r,a){t||("module"===r?(this.expectPlugin("importReflection",a),e.module=!0):this.hasPlugin("importReflection")&&(e.module=!1),"source"===r?(this.expectPlugin("sourcePhaseImports",a),e.phase="source"):"defer"===r?(this.expectPlugin("deferredImportEvaluation",a),e.phase="defer"):this.hasPlugin("sourcePhaseImports")&&(e.phase=null))},r.parseMaybeImportPhase=function(e,t){if(!this.isPotentialImportPhase(t))return this.applyImportPhase(e,t,null),null;var r=this.startNode(),a=this.parseIdentifierName(!0),n=this.state.type;return(cb(n)?98!==n||102===this.lookaheadCharCode():12!==n)?(this.applyImportPhase(e,t,a,r.loc.start),null):(this.applyImportPhase(e,t,null),this.createIdentifier(r,a))},r.isPrecedingIdImportPhase=function(e){var t=this.state.type;return db(t)?98!==t||102===this.lookaheadCharCode():12!==t},r.parseImport=function(e){return this.match(134)?this.parseImportSourceAndAttributes(e):this.parseImportSpecifiersAndAfter(e,this.parseMaybeImportPhase(e,!1))},r.parseImportSpecifiersAndAfter=function(e,t){e.specifiers=[];var r=!this.maybeParseDefaultImportSpecifier(e,t)||this.eat(12),a=r&&this.maybeParseStarImportSpecifier(e);return r&&!a&&this.parseNamedImportSpecifiers(e),this.expectContextual(98),this.parseImportSourceAndAttributes(e)},r.parseImportSourceAndAttributes=function(e){return null!=e.specifiers||(e.specifiers=[]),e.source=this.parseImportSource(),this.maybeParseImportAttributes(e),this.checkImportReflection(e),this.checkJSONModuleImport(e),this.semicolon(),this.sawUnambiguousESM=!0,this.finishNode(e,"ImportDeclaration")},r.parseImportSource=function(){return this.match(134)||this.unexpected(),this.parseExprAtom()},r.parseImportSpecifierLocal=function(e,t,r){t.local=this.parseIdentifier(),e.specifiers.push(this.finishImportSpecifier(t,r))},r.finishImportSpecifier=function(e,t,r){return void 0===r&&(r=Jb),this.checkLVal(e.local,{type:t},r),this.finishNode(e,t)},r.parseImportAttributes=function(){this.expect(5);var e=[],t=new Set;do{if(this.match(8))break;var r=this.startNode(),a=this.state.value;if(t.has(a)&&this.raise(wh.ModuleAttributesWithDuplicateKeys,this.state.startLoc,{key:a}),t.add(a),this.match(134)?r.key=this.parseStringLiteral(a):r.key=this.parseIdentifier(!0),this.expect(14),!this.match(134))throw this.raise(wh.ModuleAttributeInvalidValue,this.state.startLoc);r.value=this.parseStringLiteral(this.state.value),e.push(this.finishNode(r,"ImportAttribute"))}while(this.eat(12));return this.expect(8),e},r.parseModuleAttributes=function(){var e=[],t=new Set;do{var r=this.startNode();if(r.key=this.parseIdentifier(!0),"type"!==r.key.name&&this.raise(wh.ModuleAttributeDifferentFromType,r.key),t.has(r.key.name)&&this.raise(wh.ModuleAttributesWithDuplicateKeys,r.key,{key:r.key.name}),t.add(r.key.name),this.expect(14),!this.match(134))throw this.raise(wh.ModuleAttributeInvalidValue,this.state.startLoc);r.value=this.parseStringLiteral(this.state.value),e.push(this.finishNode(r,"ImportAttribute"))}while(this.eat(12));return e},r.maybeParseImportAttributes=function(e){var t,r=!1;if(this.match(76)){if(this.hasPrecedingLineBreak()&&40===this.lookaheadCharCode())return;this.next(),this.hasPlugin("moduleAttributes")?(t=this.parseModuleAttributes(),this.addExtra(e,"deprecatedWithLegacySyntax",!0)):t=this.parseImportAttributes(),r=!0}else this.isContextual(94)&&!this.hasPrecedingLineBreak()?(this.hasPlugin("deprecatedImportAssert")||this.hasPlugin("importAssertions")||this.raise(wh.ImportAttributesUseAssert,this.state.startLoc),this.hasPlugin("importAssertions")||this.addExtra(e,"deprecatedAssertSyntax",!0),this.next(),t=this.parseImportAttributes()):t=[];!r&&this.hasPlugin("importAssertions")?e.assertions=t:e.attributes=t},r.maybeParseDefaultImportSpecifier=function(e,t){if(t){var r=this.startNodeAtNode(t);return r.local=t,e.specifiers.push(this.finishImportSpecifier(r,"ImportDefaultSpecifier")),!0}return!!cb(this.state.type)&&(this.parseImportSpecifierLocal(e,this.startNode(),"ImportDefaultSpecifier"),!0)},r.maybeParseStarImportSpecifier=function(e){if(this.match(55)){var t=this.startNode();return this.next(),this.expectContextual(93),this.parseImportSpecifierLocal(e,t,"ImportNamespaceSpecifier"),!0}return!1},r.parseNamedImportSpecifiers=function(e){var t=!0;for(this.expect(5);!this.eat(8);){if(t)t=!1;else{if(this.eat(14))throw this.raise(wh.DestructureNamedImport,this.state.startLoc);if(this.expect(12),this.eat(8))break}var r=this.startNode(),a=this.match(134),n=this.isContextual(130);r.imported=this.parseModuleExportName();var s=this.parseImportSpecifier(r,a,"type"===e.importKind||"typeof"===e.importKind,n,void 0);e.specifiers.push(s)}},r.parseImportSpecifier=function(e,t,r,a,n){if(this.eatContextual(93))e.local=this.parseIdentifier();else{var s=e.imported;if(t)throw this.raise(wh.ImportBindingIsString,e,{importName:s.value});this.checkReservedWord(s.name,e.loc.start,!0,!0),e.local||(e.local=this.cloneIdentifier(s))}return this.finishImportSpecifier(e,"ImportSpecifier",n)},r.isThisParam=function(e){return"Identifier"===e.type&&"this"===e.name},o(t)}(qv),aR=function(e){function t(t,r,a){var n;t=function(e){var t={sourceType:"script",sourceFilename:void 0,startIndex:0,startColumn:0,startLine:1,allowAwaitOutsideFunction:!1,allowReturnOutsideFunction:!1,allowNewTargetOutsideFunction:!1,allowImportExportEverywhere:!1,allowSuperOutsideMethod:!1,allowUndeclaredExports:!1,allowYieldOutsideFunction:!1,plugins:[],strictMode:null,ranges:!1,tokens:!1,createImportExpressions:!1,createParenthesizedExpressions:!1,errorRecovery:!1,attachComment:!0,annexB:!0};if(null==e)return t;if(null!=e.annexB&&!1!==e.annexB)throw new Error("The `annexB` option can only be set to `false`.");for(var r=0,a=Object.keys(t);r0?t.startIndex=t.startColumn:null==e.startColumn&&t.startIndex>0&&(t.startColumn=t.startIndex);else if((null==e.startColumn||null==e.startIndex)&&null!=e.startIndex)throw new Error("With a `startLine > 1` you must also specify `startIndex` and `startColumn`.");if("commonjs"===t.sourceType){if(null!=e.allowAwaitOutsideFunction)throw new Error("The `allowAwaitOutsideFunction` option cannot be used with `sourceType: 'commonjs'`.");if(null!=e.allowReturnOutsideFunction)throw new Error("`sourceType: 'commonjs'` implies `allowReturnOutsideFunction: true`, please remove the `allowReturnOutsideFunction` option or use `sourceType: 'script'`.");if(null!=e.allowNewTargetOutsideFunction)throw new Error("`sourceType: 'commonjs'` implies `allowNewTargetOutsideFunction: true`, please remove the `allowNewTargetOutsideFunction` option or use `sourceType: 'script'`.")}return t}(t),(n=e.call(this,t,r)||this).options=t,n.initializeScopes(),n.plugins=a,n.filename=t.sourceFilename,n.startIndex=t.startIndex;var s=0;return t.allowAwaitOutsideFunction&&(s|=Eh),t.allowReturnOutsideFunction&&(s|=Sh),t.allowImportExportEverywhere&&(s|=Ph),t.allowSuperOutsideMethod&&(s|=Ah),t.allowUndeclaredExports&&(s|=Ch),t.allowNewTargetOutsideFunction&&(s|=Th),t.allowYieldOutsideFunction&&(s|=kh),t.ranges&&(s|=_h),t.tokens&&(s|=Ih),t.createImportExpressions&&(s|=Dh),t.createParenthesizedExpressions&&(s|=Nh),t.errorRecovery&&(s|=Oh),t.attachComment&&(s|=Bh),t.annexB&&(s|=Mh),n.optionFlags=s,n}c(t,e);var r=t.prototype;return r.getScopeHandler=function(){return Rx},r.parse=function(){this.enterInitialScopes();var e=this.startNode(),t=this.startNode();return this.nextToken(),e.errors=null,this.parseTopLevel(e,t),e.errors=this.state.errors,e.comments.length=this.state.commentsLen,e},o(t)}(rR);function nR(e,t){var r;if("unambiguous"!==(null==(r=t)?void 0:r.sourceType))return oR(t,e).parse();t=Object.assign({},t);try{t.sourceType="module";var a=oR(t,e),n=a.parse();if(a.sawUnambiguousESM)return n;if(a.ambiguousScriptDifferentAst)try{return t.sourceType="script",oR(t,e).parse()}catch(e){}else n.program.sourceType="script";return n}catch(r){try{return t.sourceType="script",oR(t,e).parse()}catch(e){}throw r}}var sR=function(e){for(var t={},r=0,a=Object.keys(e);r!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g,jR.matchToToken=function(e){var t={type:"invalid",value:e[0],closed:void 0};return e[1]?(t.type="string",t.closed=!(!e[3]&&!e[4])):e[5]?t.type="comment":e[6]?(t.type="comment",t.closed=!!e[7]):e[8]?t.type="regex":e[9]?t.type="number":e[10]?t.type="name":e[11]?t.type="punctuator":e[12]&&(t.type="whitespace"),t}),jR}var ER,SR=(void K.env.BABEL_8_BREAKING,wR()),TR=new Set(["as","async","from","get","of","set"]),PR=/\r\n|[\n\r\u2028\u2029]/,AR=/^[()[\]{}]$/,kR=/^[a-z][\w-]*$/i,CR=function(e,t,r){if("name"===e.type){if(Qr(e.value)||Jr(e.value,!0)||TR.has(e.value))return"keyword";if(kR.test(e.value)&&("<"===r[t-1]||""),n.gutter(s),e.length>0?" "+e:"",l].join("")}return" "+n.gutter(s)+(e.length>0?" "+e:"")}).join("\n");return r.message&&!l&&(f=""+" ".repeat(u+1)+r.message+"\n"+f),a?n.reset(f):f}var DR=ee,NR=ae,OR=dr,BR=de,MR=kt,FR=he,LR=Nt,UR=nr,qR=ue,GR=Pm,WR=Fm,VR=/^[_$A-Z0-9]+$/;function HR(e,t,r){var a=r.placeholderWhitelist,n=r.placeholderPattern,s=r.preserveComments,o=r.syntacticPlaceholders,i=function(e,t,r){var a=(t.plugins||[]).slice();!1!==r&&a.push("placeholders");t=Object.assign({allowAwaitOutsideFunction:!0,allowReturnOutsideFunction:!0,allowNewTargetOutsideFunction:!0,allowSuperOutsideMethod:!0,allowYieldOutsideFunction:!0,sourceType:"module"},t,{plugins:a});try{return nR(e,t)}catch(t){var n=t.loc;throw n&&(t.message+="\n"+IR(e,{start:n}),t.code="BABEL_TEMPLATE_PARSE_ERROR"),t}}(t,r.parser,o);GR(i,{preserveComments:s}),e.validate(i);var d={syntactic:{placeholders:[],placeholderNames:new Set},legacy:{placeholders:[],placeholderNames:new Set},placeholderWhitelist:a,placeholderPattern:n,syntacticPlaceholders:o};return WR(i,KR,d),Object.assign({ast:i},d.syntactic.placeholders.length?d.syntactic:d.legacy)}function KR(e,t,r){var a,n,s=r.syntactic.placeholders.length>0;if(LR(e)){if(!1===r.syntacticPlaceholders)throw new Error("%%foo%%-style placeholders can't be used when '.syntacticPlaceholders' is false.");n=e.name.name,s=!0}else{if(s||r.syntacticPlaceholders)return;if(BR(e)||MR(e))n=e.name;else{if(!qR(e))return;n=e.value}}if(s&&(null!=r.placeholderPattern||null!=r.placeholderWhitelist))throw new Error("'.placeholderWhitelist' and '.placeholderPattern' aren't compatible with '.syntacticPlaceholders: true'");if(s||!1!==r.placeholderPattern&&(r.placeholderPattern||VR).test(n)||null!=(a=r.placeholderWhitelist)&&a.has(n)){var o,i=(t=t.slice())[t.length-1],d=i.node,c=i.key;qR(e)||LR(e,{expectedNode:"StringLiteral"})?o="string":FR(d)&&"arguments"===c||DR(d)&&"arguments"===c||OR(d)&&"params"===c?o="param":NR(d)&&!LR(e)?(o="statement",t=t.slice(0,-1)):o=UR(e)&&LR(e)?"statement":"other";var l=s?r.syntactic:r.legacy,u=l.placeholders,p=l.placeholderNames;u.push({name:n,type:o,resolve:function(e){return function(e,t){for(var r=e,a=0;a1?a-1:0),o=1;o1)throw new Error("Unexpected extra params.");return ij(aj(e,t,sh(n,oh(s[0]))))}if(Array.isArray(t)){var i=r.get(t);return i||(i=nj(e,t,n),r.set(t,i)),ij(i(s))}if("object"==typeof t&&t){if(s.length>0)throw new Error("Unexpected extra params.");return oj(e,sh(n,oh(t)))}throw new Error("Unexpected template param "+typeof t)},{ast:function(t){for(var r=arguments.length,s=new Array(r>1?r-1:0),o=1;o1)throw new Error("Unexpected extra params.");return aj(e,t,sh(sh(n,oh(s[0])),sj))()}if(Array.isArray(t)){var i=a.get(t);return i||(i=nj(e,t,sh(n,sj)),a.set(t,i)),i(s)()}throw new Error("Unexpected template param "+typeof t)}})}function ij(e){var t="";try{throw new Error}catch(e){e.stack&&(t=e.stack.split("\n").slice(3).join("\n"))}return function(r){try{return e(r)}catch(e){throw e.stack+="\n =============\n"+t,e}}}var dj=oj(eh),cj=oj(rh),lj=oj(th),uj=oj(ah),pj=oj({code:function(e){return e},validate:function(){},unwrap:function(e){return e.program}}),fj=Object.assign(dj.bind(void 0),{smart:dj,statement:cj,statements:lj,expression:uj,program:pj,ast:dj.ast}),gj=Object.freeze({__proto__:null,default:fj,expression:uj,program:pj,smart:dj,statement:cj,statements:lj});function yj(e,t,r){return Object.freeze({minVersion:e,ast:function(){return fj.program.ast(t,{preserveComments:!0})},metadata:r})}var mj={__proto__:null,OverloadYield:yj("7.18.14","function _OverloadYield(e,d){this.v=e,this.k=d}",{globals:[],locals:{_OverloadYield:["body.0.id"]},exportBindingAssignments:[],exportName:"_OverloadYield",dependencies:{},internal:!1}),applyDecoratedDescriptor:yj("7.0.0-beta.0",'function _applyDecoratedDescriptor(i,e,r,n,l){var a={};return Object.keys(n).forEach(function(i){a[i]=n[i]}),a.enumerable=!!a.enumerable,a.configurable=!!a.configurable,("value"in a||a.initializer)&&(a.writable=!0),a=r.slice().reverse().reduce(function(r,n){return n(i,e,r)||r},a),l&&void 0!==a.initializer&&(a.value=a.initializer?a.initializer.call(l):void 0,a.initializer=void 0),void 0===a.initializer?(Object.defineProperty(i,e,a),null):a}',{globals:["Object"],locals:{_applyDecoratedDescriptor:["body.0.id"]},exportBindingAssignments:[],exportName:"_applyDecoratedDescriptor",dependencies:{},internal:!1}),applyDecs2311:yj("7.24.0",'function applyDecs2311(e,t,n,r,o,i){var a,c,u,s,f,l,p,d=Symbol.metadata||Symbol.for("Symbol.metadata"),m=Object.defineProperty,h=Object.create,y=[h(null),h(null)],v=t.length;function g(t,n,r){return function(o,i){n&&(i=o,o=e);for(var a=0;a=0;O-=n?2:1){var T=b(h[O],"A decorator","be",!0),z=n?h[O-1]:void 0,A={},H={kind:["field","accessor","method","getter","setter","class"][o],name:r,metadata:a,addInitializer:function(e,t){if(e.v)throw new TypeError("attempted to call addInitializer after decoration was finished");b(t,"An initializer","be",!0),i.push(t)}.bind(null,A)};if(w)c=T.call(z,N,H),A.v=1,b(c,"class decorators","return")&&(N=c);else if(H.static=s,H.private=f,c=H.access={has:f?p.bind():function(e){return r in e}},j||(c.get=f?E?function(e){return d(e),P.value}:I("get",0,d):function(e){return e[r]}),E||S||(c.set=f?I("set",0,d):function(e,t){e[r]=t}),N=T.call(z,D?{get:P.get,set:P.set}:P[F],H),A.v=1,D){if("object"==typeof N&&N)(c=b(N.get,"accessor.get"))&&(P.get=c),(c=b(N.set,"accessor.set"))&&(P.set=c),(c=b(N.init,"accessor.init"))&&k.unshift(c);else if(void 0!==N)throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined")}else b(N,(l?"field":"method")+" decorators","return")&&(l?k.unshift(N):P[F]=N)}return o<2&&u.push(g(k,s,1),g(i,s,0)),l||w||(f?D?u.splice(-1,0,I("get",s),I("set",s)):u.push(E?P[F]:b.call.bind(P[F])):m(e,r,P)),N}function w(e){return m(e,d,{configurable:!0,enumerable:!0,value:a})}return void 0!==i&&(a=i[d]),a=h(null==a?null:a),f=[],l=function(e){e&&f.push(g(e))},p=function(t,r){for(var i=0;ir.length)&&(a=r.length);for(var e=0,n=Array(a);e=r.length?{done:!0}:{done:!1,value:r[n++]}},e:function(r){throw r},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function(){t=t.call(r)},n:function(){var r=t.next();return a=r.done,r},e:function(r){u=!0,o=r},f:function(){try{a||null==t.return||t.return()}finally{if(u)throw o}}}}',{globals:["Symbol","Array","TypeError"],locals:{_createForOfIteratorHelper:["body.0.id"]},exportBindingAssignments:[],exportName:"_createForOfIteratorHelper",dependencies:{unsupportedIterableToArray:["body.0.body.body.1.consequent.body.0.test.left.right.right.callee"]},internal:!1}),createForOfIteratorHelperLoose:yj("7.9.0",'function _createForOfIteratorHelperLoose(r,e){var t="undefined"!=typeof Symbol&&r[Symbol.iterator]||r["@@iterator"];if(t)return(t=t.call(r)).next.bind(t);if(Array.isArray(r)||(t=unsupportedIterableToArray(r))||e&&r&&"number"==typeof r.length){t&&(r=t);var o=0;return function(){return o>=r.length?{done:!0}:{done:!1,value:r[o++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}',{globals:["Symbol","Array","TypeError"],locals:{_createForOfIteratorHelperLoose:["body.0.id"]},exportBindingAssignments:[],exportName:"_createForOfIteratorHelperLoose",dependencies:{unsupportedIterableToArray:["body.0.body.body.2.test.left.right.right.callee"]},internal:!1}),createSuper:yj("7.9.0","function _createSuper(t){var r=isNativeReflectConstruct();return function(){var e,o=getPrototypeOf(t);if(r){var s=getPrototypeOf(this).constructor;e=Reflect.construct(o,arguments,s)}else e=o.apply(this,arguments);return possibleConstructorReturn(this,e)}}",{globals:["Reflect"],locals:{_createSuper:["body.0.id"]},exportBindingAssignments:[],exportName:"_createSuper",dependencies:{getPrototypeOf:["body.0.body.body.1.argument.body.body.0.declarations.1.init.callee","body.0.body.body.1.argument.body.body.1.consequent.body.0.declarations.0.init.object.callee"],isNativeReflectConstruct:["body.0.body.body.0.declarations.0.init.callee"],possibleConstructorReturn:["body.0.body.body.1.argument.body.body.2.argument.callee"]},internal:!1}),decorate:yj("7.1.5",'function _decorate(e,r,t,i){var o=_getDecoratorsApi();if(i)for(var n=0;n=0;n--){var s=r[e.placement];s.splice(s.indexOf(e.key),1);var a=this.fromElementDescriptor(e),l=this.toElementFinisherExtras((0,o[n])(a)||a);e=l.element,this.addElementPlacement(e,r),l.finisher&&i.push(l.finisher);var c=l.extras;if(c){for(var p=0;p=0;i--){var o=this.fromClassDescriptor(e),n=this.toClassDescriptor((0,r[i])(o)||o);if(void 0!==n.finisher&&t.push(n.finisher),void 0!==n.elements){e=n.elements;for(var s=0;s1){for(var t=Array(n),f=0;f3?(o=l===n)&&(u=i[(c=i[4])?5:(c=3,3)],i[4]=i[5]=e):i[0]<=d&&((o=r<2&&dn||n>l)&&(i[4]=r,i[5]=n,G.n=l,c=0))}if(o||r>1)return a;throw y=!0,n}return function(o,p,l){if(f>1)throw TypeError("Generator is already running");for(y&&1===p&&d(p,l),c=p,u=l;(t=c<2?e:u)||!y;){i||(c?c<3?(c>1&&(G.n=-1),d(c,u)):G.n=u:G.v=u);try{if(f=2,i){if(c||(o="next"),t=i[o]){if(!(t=t.call(i,u)))throw TypeError("iterator result is not an object");if(!t.done)return t;u=t.value,c<2&&(c=0)}else 1===c&&(t=i.return)&&t.call(i),c<2&&(u=TypeError("The iterator does not provide a \'"+o+"\' method"),c=1);i=e}else if((t=(y=G.n<0)?u:r.call(n,G))!==a)break}catch(t){i=e,c=1,u=t}finally{f=1}}return{value:t,done:y}}}(r,o,i),!0),u}var a={};function Generator(){}function GeneratorFunction(){}function GeneratorFunctionPrototype(){}t=Object.getPrototypeOf;var c=[][n]?t(t([][n]())):(define(t={},n,function(){return this}),t),u=GeneratorFunctionPrototype.prototype=Generator.prototype=Object.create(c);function f(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,GeneratorFunctionPrototype):(e.__proto__=GeneratorFunctionPrototype,define(e,o,"GeneratorFunction")),e.prototype=Object.create(u),e}return GeneratorFunction.prototype=GeneratorFunctionPrototype,define(u,"constructor",GeneratorFunctionPrototype),define(GeneratorFunctionPrototype,"constructor",GeneratorFunction),GeneratorFunction.displayName="GeneratorFunction",define(GeneratorFunctionPrototype,o,"GeneratorFunction"),define(u),define(u,o,"Generator"),define(u,n,function(){return this}),define(u,"toString",function(){return"[object Generator]"}),(_regenerator=function(){return{w:i,m:f}})()}',{globals:["Symbol","Object","TypeError"],locals:{_regenerator:["body.0.id","body.0.body.body.9.argument.expressions.9.callee.left"]},exportBindingAssignments:["body.0.body.body.9.argument.expressions.9.callee"],exportName:"_regenerator",dependencies:{regeneratorDefine:["body.0.body.body.1.body.body.1.argument.expressions.0.callee","body.0.body.body.7.declarations.0.init.alternate.expressions.0.callee","body.0.body.body.8.body.body.0.argument.expressions.0.alternate.expressions.1.callee","body.0.body.body.9.argument.expressions.1.callee","body.0.body.body.9.argument.expressions.2.callee","body.0.body.body.9.argument.expressions.4.callee","body.0.body.body.9.argument.expressions.5.callee","body.0.body.body.9.argument.expressions.6.callee","body.0.body.body.9.argument.expressions.7.callee","body.0.body.body.9.argument.expressions.8.callee"]},internal:!1}),regeneratorAsync:yj("7.27.0","function _regeneratorAsync(n,e,r,t,o){var a=asyncGen(n,e,r,t,o);return a.next().then(function(n){return n.done?n.value:a.next()})}",{globals:[],locals:{_regeneratorAsync:["body.0.id"]},exportBindingAssignments:[],exportName:"_regeneratorAsync",dependencies:{regeneratorAsyncGen:["body.0.body.body.0.declarations.0.init.callee"]},internal:!1}),regeneratorAsyncGen:yj("7.27.0","function _regeneratorAsyncGen(r,e,t,o,n){return new regeneratorAsyncIterator(regenerator().w(r,e,t,o),n||Promise)}",{globals:["Promise"],locals:{_regeneratorAsyncGen:["body.0.id"]},exportBindingAssignments:[],exportName:"_regeneratorAsyncGen",dependencies:{regenerator:["body.0.body.body.0.argument.arguments.0.callee.object.callee"],regeneratorAsyncIterator:["body.0.body.body.0.argument.callee"]},internal:!1}),regeneratorAsyncIterator:yj("7.27.0",'function AsyncIterator(t,e){function n(r,o,i,f){try{var c=t[r](o),u=c.value;return u instanceof OverloadYield?e.resolve(u.v).then(function(t){n("next",t,i,f)},function(t){n("throw",t,i,f)}):e.resolve(u).then(function(t){c.value=t,i(c)},function(t){return n("throw",t,i,f)})}catch(t){f(t)}}var r;this.next||(define(AsyncIterator.prototype),define(AsyncIterator.prototype,"function"==typeof Symbol&&Symbol.asyncIterator||"@asyncIterator",function(){return this})),define(this,"_invoke",function(t,o,i){function f(){return new e(function(e,r){n(t,i,e,r)})}return r=r?r.then(f,f):f()},!0)}',{globals:["Symbol"],locals:{AsyncIterator:["body.0.id","body.0.body.body.2.expression.expressions.0.right.expressions.0.arguments.0.object","body.0.body.body.2.expression.expressions.0.right.expressions.1.arguments.0.object"]},exportBindingAssignments:[],exportName:"AsyncIterator",dependencies:{OverloadYield:["body.0.body.body.0.body.body.0.block.body.1.argument.test.right"],regeneratorDefine:["body.0.body.body.2.expression.expressions.0.right.expressions.0.callee","body.0.body.body.2.expression.expressions.0.right.expressions.1.callee","body.0.body.body.2.expression.expressions.1.callee"]},internal:!0}),regeneratorDefine:yj("7.27.0",'function regeneratorDefine(e,r,n,t){var i=Object.defineProperty;try{i({},"",{})}catch(e){i=0}regeneratorDefine=function(e,r,n,t){function o(r,n){regeneratorDefine(e,r,function(e){return this._invoke(r,n,e)})}r?i?i(e,r,{value:n,enumerable:!t,configurable:!t,writable:!t}):e[r]=n:(o("next",0),o("throw",1),o("return",2))},regeneratorDefine(e,r,n,t)}',{globals:["Object"],locals:{regeneratorDefine:["body.0.id","body.0.body.body.2.expression.expressions.0.right.body.body.0.body.body.0.expression.callee","body.0.body.body.2.expression.expressions.1.callee","body.0.body.body.2.expression.expressions.0.left"]},exportBindingAssignments:["body.0.body.body.2.expression.expressions.0"],exportName:"regeneratorDefine",dependencies:{},internal:!0}),regeneratorKeys:yj("7.27.0","function _regeneratorKeys(e){var n=Object(e),r=[];for(var t in n)r.unshift(t);return function e(){for(;r.length;)if((t=r.pop())in n)return e.value=t,e.done=!1,e;return e.done=!0,e}}",{globals:["Object"],locals:{_regeneratorKeys:["body.0.id"]},exportBindingAssignments:[],exportName:"_regeneratorKeys",dependencies:{},internal:!1}),regeneratorValues:yj("7.18.0",'function _regeneratorValues(e){if(null!=e){var t=e["function"==typeof Symbol&&Symbol.iterator||"@@iterator"],r=0;if(t)return t.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length))return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}}}throw new TypeError(typeof e+" is not iterable")}',{globals:["Symbol","isNaN","TypeError"],locals:{_regeneratorValues:["body.0.id"]},exportBindingAssignments:[],exportName:"_regeneratorValues",dependencies:{},internal:!1}),set:yj("7.0.0-beta.0",'function set(e,r,t,o){return set="undefined"!=typeof Reflect&&Reflect.set?Reflect.set:function(e,r,t,o){var f,i=superPropBase(e,r);if(i){if((f=Object.getOwnPropertyDescriptor(i,r)).set)return f.set.call(o,t),!0;if(!f.writable)return!1}if(f=Object.getOwnPropertyDescriptor(o,r)){if(!f.writable)return!1;f.value=t,Object.defineProperty(o,r,f)}else defineProperty(o,r,t);return!0},set(e,r,t,o)}function _set(e,r,t,o,f){if(!set(e,r,t,o||e)&&f)throw new TypeError("failed to set property");return t}',{globals:["Reflect","Object","TypeError"],locals:{set:["body.0.id","body.0.body.body.0.argument.expressions.1.callee","body.1.body.body.0.test.left.argument.callee","body.0.body.body.0.argument.expressions.0.left"],_set:["body.1.id"]},exportBindingAssignments:[],exportName:"_set",dependencies:{superPropBase:["body.0.body.body.0.argument.expressions.0.right.alternate.body.body.0.declarations.1.init.callee"],defineProperty:["body.0.body.body.0.argument.expressions.0.right.alternate.body.body.2.alternate.expression.callee"]},internal:!1}),setFunctionName:yj("7.23.6",'function setFunctionName(e,t,n){"symbol"==typeof t&&(t=(t=t.description)?"["+t+"]":"");try{Object.defineProperty(e,"name",{configurable:!0,value:n?n+" "+t:t})}catch(e){}return e}',{globals:["Object"],locals:{setFunctionName:["body.0.id"]},exportBindingAssignments:[],exportName:"setFunctionName",dependencies:{},internal:!1}),setPrototypeOf:yj("7.0.0-beta.0","function _setPrototypeOf(t,e){return _setPrototypeOf=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},_setPrototypeOf(t,e)}",{globals:["Object"],locals:{_setPrototypeOf:["body.0.id","body.0.body.body.0.argument.expressions.1.callee","body.0.body.body.0.argument.expressions.0.left"]},exportBindingAssignments:["body.0.body.body.0.argument.expressions.0"],exportName:"_setPrototypeOf",dependencies:{},internal:!1}),skipFirstGeneratorNext:yj("7.0.0-beta.0","function _skipFirstGeneratorNext(t){return function(){var r=t.apply(this,arguments);return r.next(),r}}",{globals:[],locals:{_skipFirstGeneratorNext:["body.0.id"]},exportBindingAssignments:[],exportName:"_skipFirstGeneratorNext",dependencies:{},internal:!1}),slicedToArray:yj("7.0.0-beta.0","function _slicedToArray(r,e){return arrayWithHoles(r)||iterableToArrayLimit(r,e)||unsupportedIterableToArray(r,e)||nonIterableRest()}",{globals:[],locals:{_slicedToArray:["body.0.id"]},exportBindingAssignments:[],exportName:"_slicedToArray",dependencies:{arrayWithHoles:["body.0.body.body.0.argument.left.left.left.callee"],iterableToArrayLimit:["body.0.body.body.0.argument.left.left.right.callee"],unsupportedIterableToArray:["body.0.body.body.0.argument.left.right.callee"],nonIterableRest:["body.0.body.body.0.argument.right.callee"]},internal:!1}),superPropBase:yj("7.0.0-beta.0","function _superPropBase(t,o){for(;!{}.hasOwnProperty.call(t,o)&&null!==(t=getPrototypeOf(t)););return t}",{globals:[],locals:{_superPropBase:["body.0.id"]},exportBindingAssignments:[],exportName:"_superPropBase",dependencies:{getPrototypeOf:["body.0.body.body.0.test.right.right.right.callee"]},internal:!1}),superPropGet:yj("7.25.0",'function _superPropGet(t,o,e,r){var p=get(getPrototypeOf(1&r?t.prototype:t),o,e);return 2&r&&"function"==typeof p?function(t){return p.apply(e,t)}:p}',{globals:[],locals:{_superPropGet:["body.0.id"]},exportBindingAssignments:[],exportName:"_superPropGet",dependencies:{get:["body.0.body.body.0.declarations.0.init.callee"],getPrototypeOf:["body.0.body.body.0.declarations.0.init.arguments.0.callee"]},internal:!1}),superPropSet:yj("7.25.0","function _superPropSet(t,e,o,r,p,f){return set(getPrototypeOf(f?t.prototype:t),e,o,r,p)}",{globals:[],locals:{_superPropSet:["body.0.id"]},exportBindingAssignments:[],exportName:"_superPropSet",dependencies:{set:["body.0.body.body.0.argument.callee"],getPrototypeOf:["body.0.body.body.0.argument.arguments.0.callee"]},internal:!1}),taggedTemplateLiteral:yj("7.0.0-beta.0","function _taggedTemplateLiteral(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}",{globals:["Object"],locals:{_taggedTemplateLiteral:["body.0.id"]},exportBindingAssignments:[],exportName:"_taggedTemplateLiteral",dependencies:{},internal:!1}),taggedTemplateLiteralLoose:yj("7.0.0-beta.0","function _taggedTemplateLiteralLoose(e,t){return t||(t=e.slice(0)),e.raw=t,e}",{globals:[],locals:{_taggedTemplateLiteralLoose:["body.0.id"]},exportBindingAssignments:[],exportName:"_taggedTemplateLiteralLoose",dependencies:{},internal:!1}),tdz:yj("7.5.5",'function _tdzError(e){throw new ReferenceError(e+" is not defined - temporal dead zone")}',{globals:["ReferenceError"],locals:{_tdzError:["body.0.id"]},exportBindingAssignments:[],exportName:"_tdzError",dependencies:{},internal:!1}),temporalRef:yj("7.0.0-beta.0","function _temporalRef(r,e){return r===undef?err(e):r}",{globals:[],locals:{_temporalRef:["body.0.id"]},exportBindingAssignments:[],exportName:"_temporalRef",dependencies:{temporalUndefined:["body.0.body.body.0.argument.test.right"],tdz:["body.0.body.body.0.argument.consequent.callee"]},internal:!1}),temporalUndefined:yj("7.0.0-beta.0","function _temporalUndefined(){}",{globals:[],locals:{_temporalUndefined:["body.0.id"]},exportBindingAssignments:[],exportName:"_temporalUndefined",dependencies:{},internal:!1}),toArray:yj("7.0.0-beta.0","function _toArray(r){return arrayWithHoles(r)||iterableToArray(r)||unsupportedIterableToArray(r)||nonIterableRest()}",{globals:[],locals:{_toArray:["body.0.id"]},exportBindingAssignments:[],exportName:"_toArray",dependencies:{arrayWithHoles:["body.0.body.body.0.argument.left.left.left.callee"],iterableToArray:["body.0.body.body.0.argument.left.left.right.callee"],unsupportedIterableToArray:["body.0.body.body.0.argument.left.right.callee"],nonIterableRest:["body.0.body.body.0.argument.right.callee"]},internal:!1}),toConsumableArray:yj("7.0.0-beta.0","function _toConsumableArray(r){return arrayWithoutHoles(r)||iterableToArray(r)||unsupportedIterableToArray(r)||nonIterableSpread()}",{globals:[],locals:{_toConsumableArray:["body.0.id"]},exportBindingAssignments:[],exportName:"_toConsumableArray",dependencies:{arrayWithoutHoles:["body.0.body.body.0.argument.left.left.left.callee"],iterableToArray:["body.0.body.body.0.argument.left.left.right.callee"],unsupportedIterableToArray:["body.0.body.body.0.argument.left.right.callee"],nonIterableSpread:["body.0.body.body.0.argument.right.callee"]},internal:!1}),toPrimitive:yj("7.1.5",'function toPrimitive(t,r){if("object"!=typeof t||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,r||"default");if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===r?String:Number)(t)}',{globals:["Symbol","TypeError","String","Number"],locals:{toPrimitive:["body.0.id"]},exportBindingAssignments:[],exportName:"toPrimitive",dependencies:{},internal:!1}),toPropertyKey:yj("7.1.5",'function toPropertyKey(t){var i=toPrimitive(t,"string");return"symbol"==typeof i?i:i+""}',{globals:[],locals:{toPropertyKey:["body.0.id"]},exportBindingAssignments:[],exportName:"toPropertyKey",dependencies:{toPrimitive:["body.0.body.body.0.declarations.0.init.callee"]},internal:!1}),toSetter:yj("7.24.0",'function _toSetter(t,e,n){e||(e=[]);var r=e.length++;return Object.defineProperty({},"_",{set:function(o){e[r]=o,t.apply(n,e)}})}',{globals:["Object"],locals:{_toSetter:["body.0.id"]},exportBindingAssignments:[],exportName:"_toSetter",dependencies:{},internal:!1}),tsRewriteRelativeImportExtensions:yj("7.27.0",'function tsRewriteRelativeImportExtensions(t,e){return"string"==typeof t&&/^\\.\\.?\\//.test(t)?t.replace(/\\.(tsx)$|((?:\\.d)?)((?:\\.[^./]+)?)\\.([cm]?)ts$/i,function(t,s,r,n,o){return s?e?".jsx":".js":!r||n&&o?r+n+"."+o.toLowerCase()+"js":t}):t}',{globals:[],locals:{tsRewriteRelativeImportExtensions:["body.0.id"]},exportBindingAssignments:[],exportName:"tsRewriteRelativeImportExtensions",dependencies:{},internal:!1}),typeof:yj("7.0.0-beta.0",'function _typeof(o){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},_typeof(o)}',{globals:["Symbol"],locals:{_typeof:["body.0.id","body.0.body.body.0.argument.expressions.1.callee","body.0.body.body.0.argument.expressions.0.left"]},exportBindingAssignments:["body.0.body.body.0.argument.expressions.0"],exportName:"_typeof",dependencies:{},internal:!1}),unsupportedIterableToArray:yj("7.9.0",'function _unsupportedIterableToArray(r,a){if(r){if("string"==typeof r)return arrayLikeToArray(r,a);var t={}.toString.call(r).slice(8,-1);return"Object"===t&&r.constructor&&(t=r.constructor.name),"Map"===t||"Set"===t?Array.from(r):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?arrayLikeToArray(r,a):void 0}}',{globals:["Array"],locals:{_unsupportedIterableToArray:["body.0.id"]},exportBindingAssignments:[],exportName:"_unsupportedIterableToArray",dependencies:{arrayLikeToArray:["body.0.body.body.0.consequent.body.0.consequent.argument.callee","body.0.body.body.0.consequent.body.2.argument.expressions.1.alternate.consequent.callee"]},internal:!1}),usingCtx:yj("7.23.9",'function _usingCtx(){var r="function"==typeof SuppressedError?SuppressedError:function(r,e){var n=Error();return n.name="SuppressedError",n.error=r,n.suppressed=e,n},e={},n=[];function using(r,e){if(null!=e){if(Object(e)!==e)throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");if(r)var o=e[Symbol.asyncDispose||Symbol.for("Symbol.asyncDispose")];if(void 0===o&&(o=e[Symbol.dispose||Symbol.for("Symbol.dispose")],r))var t=o;if("function"!=typeof o)throw new TypeError("Object is not disposable.");t&&(o=function(){try{t.call(e)}catch(r){return Promise.reject(r)}}),n.push({v:e,d:o,a:r})}else r&&n.push({d:e,a:r});return e}return{e:e,u:using.bind(null,!1),a:using.bind(null,!0),d:function(){var o,t=this.e,s=0;function next(){for(;o=n.pop();)try{if(!o.a&&1===s)return s=0,n.push(o),Promise.resolve().then(next);if(o.d){var r=o.d.call(o.v);if(o.a)return s|=2,Promise.resolve(r).then(next,err)}else s|=1}catch(r){return err(r)}if(1===s)return t!==e?Promise.reject(t):Promise.resolve();if(t!==e)throw t}function err(n){return t=t!==e?new r(n,t):n,next()}return next()}}}',{globals:["SuppressedError","Error","Object","TypeError","Symbol","Promise"],locals:{_usingCtx:["body.0.id"]},exportBindingAssignments:[],exportName:"_usingCtx",dependencies:{},internal:!1}),wrapAsyncGenerator:yj("7.0.0-beta.0",'function _wrapAsyncGenerator(e){return function(){return new AsyncGenerator(e.apply(this,arguments))}}function AsyncGenerator(e){var r,t;function resume(r,t){try{var n=e[r](t),o=n.value,u=o instanceof OverloadYield;Promise.resolve(u?o.v:o).then(function(t){if(u){var i="return"===r?"return":"next";if(!o.k||t.done)return resume(i,t);t=e[i](t).value}settle(n.done?"return":"normal",t)},function(e){resume("throw",e)})}catch(e){settle("throw",e)}}function settle(e,n){switch(e){case"return":r.resolve({value:n,done:!0});break;case"throw":r.reject(n);break;default:r.resolve({value:n,done:!1})}(r=r.next)?resume(r.key,r.arg):t=null}this._invoke=function(e,n){return new Promise(function(o,u){var i={key:e,arg:n,resolve:o,reject:u,next:null};t?t=t.next=i:(r=t=i,resume(e,n))})},"function"!=typeof e.return&&(this.return=void 0)}AsyncGenerator.prototype["function"==typeof Symbol&&Symbol.asyncIterator||"@@asyncIterator"]=function(){return this},AsyncGenerator.prototype.next=function(e){return this._invoke("next",e)},AsyncGenerator.prototype.throw=function(e){return this._invoke("throw",e)},AsyncGenerator.prototype.return=function(e){return this._invoke("return",e)};',{globals:["Promise","Symbol"],locals:{_wrapAsyncGenerator:["body.0.id"],AsyncGenerator:["body.1.id","body.0.body.body.0.argument.body.body.0.argument.callee","body.2.expression.expressions.0.left.object.object","body.2.expression.expressions.1.left.object.object","body.2.expression.expressions.2.left.object.object","body.2.expression.expressions.3.left.object.object"]},exportBindingAssignments:[],exportName:"_wrapAsyncGenerator",dependencies:{OverloadYield:["body.1.body.body.1.body.body.0.block.body.0.declarations.2.init.right"]},internal:!1}),wrapNativeSuper:yj("7.0.0-beta.0",'function _wrapNativeSuper(t){var r="function"==typeof Map?new Map:void 0;return _wrapNativeSuper=function(t){if(null===t||!isNativeFunction(t))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==r){if(r.has(t))return r.get(t);r.set(t,Wrapper)}function Wrapper(){return construct(t,arguments,getPrototypeOf(this).constructor)}return Wrapper.prototype=Object.create(t.prototype,{constructor:{value:Wrapper,enumerable:!1,writable:!0,configurable:!0}}),setPrototypeOf(Wrapper,t)},_wrapNativeSuper(t)}',{globals:["Map","TypeError","Object"],locals:{_wrapNativeSuper:["body.0.id","body.0.body.body.1.argument.expressions.1.callee","body.0.body.body.1.argument.expressions.0.left"]},exportBindingAssignments:["body.0.body.body.1.argument.expressions.0"],exportName:"_wrapNativeSuper",dependencies:{getPrototypeOf:["body.0.body.body.1.argument.expressions.0.right.body.body.3.body.body.0.argument.arguments.2.object.callee"],setPrototypeOf:["body.0.body.body.1.argument.expressions.0.right.body.body.4.argument.expressions.1.callee"],isNativeFunction:["body.0.body.body.1.argument.expressions.0.right.body.body.0.test.right.argument.callee"],construct:["body.0.body.body.1.argument.expressions.0.right.body.body.3.body.body.0.argument.callee"]},internal:!1}),wrapRegExp:yj("7.19.0",'function _wrapRegExp(){_wrapRegExp=function(e,r){return new BabelRegExp(e,void 0,r)};var e=RegExp.prototype,r=new WeakMap;function BabelRegExp(e,t,p){var o=RegExp(e,t);return r.set(o,p||r.get(e)),setPrototypeOf(o,BabelRegExp.prototype)}function buildGroups(e,t){var p=r.get(t);return Object.keys(p).reduce(function(r,t){var o=p[t];if("number"==typeof o)r[t]=e[o];else{for(var i=0;void 0===e[o[i]]&&i+1]+)(>|$)/g,function(e,r,t){if(""===t)return e;var p=o[r];return Array.isArray(p)?"$"+p.join("$"):"number"==typeof p?"$"+p:""}))}if("function"==typeof p){var i=this;return e[Symbol.replace].call(this,t,function(){var e=arguments;return"object"!=typeof e[e.length-1]&&(e=[].slice.call(e)).push(buildGroups(e,i)),p.apply(this,e)})}return e[Symbol.replace].call(this,t,p)},_wrapRegExp.apply(this,arguments)}',{globals:["RegExp","WeakMap","Object","Symbol","Array"],locals:{_wrapRegExp:["body.0.id","body.0.body.body.4.argument.expressions.3.callee.object","body.0.body.body.0.expression.left"]},exportBindingAssignments:["body.0.body.body.0.expression"],exportName:"_wrapRegExp",dependencies:{setPrototypeOf:["body.0.body.body.2.body.body.1.argument.expressions.1.callee"],inherits:["body.0.body.body.4.argument.expressions.0.callee"]},internal:!1}),writeOnlyError:yj("7.12.13","function _writeOnlyError(r){throw new TypeError('\"'+r+'\" is write-only')}",{globals:["TypeError"],locals:{_writeOnlyError:["body.0.id"]},exportBindingAssignments:[],exportName:"_writeOnlyError",dependencies:{},internal:!1})};Object.assign(mj,{AwaitValue:yj("7.0.0-beta.0","function _AwaitValue(t){this.wrapped=t}",{globals:[],locals:{_AwaitValue:["body.0.id"]},exportBindingAssignments:[],exportName:"_AwaitValue",dependencies:{},internal:!1}),applyDecs:yj("7.17.8",'function old_createMetadataMethodsForProperty(e,t,a,r){return{getMetadata:function(o){old_assertNotFinished(r,"getMetadata"),old_assertMetadataKey(o);var i=e[o];if(void 0!==i)if(1===t){var n=i.public;if(void 0!==n)return n[a]}else if(2===t){var l=i.private;if(void 0!==l)return l.get(a)}else if(Object.hasOwnProperty.call(i,"constructor"))return i.constructor},setMetadata:function(o,i){old_assertNotFinished(r,"setMetadata"),old_assertMetadataKey(o);var n=e[o];if(void 0===n&&(n=e[o]={}),1===t){var l=n.public;void 0===l&&(l=n.public={}),l[a]=i}else if(2===t){var s=n.priv;void 0===s&&(s=n.private=new Map),s.set(a,i)}else n.constructor=i}}}function old_convertMetadataMapToFinal(e,t){var a=e[Symbol.metadata||Symbol.for("Symbol.metadata")],r=Object.getOwnPropertySymbols(t);if(0!==r.length){for(var o=0;o=0;m--){var b;void 0!==(p=old_memberDec(h[m],r,c,l,s,o,i,n,f))&&(old_assertValidReturnValue(o,p),0===o?b=p:1===o?(b=old_getInit(p),v=p.get||f.get,y=p.set||f.set,f={get:v,set:y}):f=p,void 0!==b&&(void 0===d?d=b:"function"==typeof d?d=[d,b]:d.push(b)))}if(0===o||1===o){if(void 0===d)d=function(e,t){return t};else if("function"!=typeof d){var g=d;d=function(e,t){for(var a=t,r=0;r3,m=v>=5;if(m?(u=t,f=r,0!=(v-=5)&&(p=n=n||[])):(u=t.prototype,f=a,0!==v&&(p=i=i||[])),0!==v&&!h){var b=m?s:l,g=b.get(y)||0;if(!0===g||3===g&&4!==v||4===g&&3!==v)throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: "+y);!g&&v>2?b.set(y,v):b.set(y,!0)}old_applyMemberDec(e,u,d,y,v,m,h,f,p)}}old_pushInitializers(e,i),old_pushInitializers(e,n)}function old_pushInitializers(e,t){t&&e.push(function(e){for(var a=0;a0){for(var o=[],i=t,n=t.name,l=r.length-1;l>=0;l--){var s={v:!1};try{var c=Object.assign({kind:"class",name:n,addInitializer:old_createAddInitializerMethod(o,s)},old_createMetadataMethodsForProperty(a,0,n,s)),d=r[l](i,c)}finally{s.v=!0}void 0!==d&&(old_assertValidReturnValue(10,d),i=d)}e.push(i,function(){for(var e=0;e=0;v--){var g;void 0!==(f=memberDec(h[v],a,c,o,n,i,s,u))&&(assertValidReturnValue(n,f),0===n?g=f:1===n?(g=f.init,p=f.get||u.get,d=f.set||u.set,u={get:p,set:d}):u=f,void 0!==g&&(void 0===l?l=g:"function"==typeof l?l=[l,g]:l.push(g)))}if(0===n||1===n){if(void 0===l)l=function(e,t){return t};else if("function"!=typeof l){var y=l;l=function(e,t){for(var r=t,a=0;a3,h=f>=5;if(h?(l=t,0!=(f-=5)&&(u=n=n||[])):(l=t.prototype,0!==f&&(u=a=a||[])),0!==f&&!d){var v=h?s:i,g=v.get(p)||0;if(!0===g||3===g&&4!==f||4===g&&3!==f)throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: "+p);!g&&f>2?v.set(p,f):v.set(p,!0)}applyMemberDec(e,l,c,p,f,h,d,u)}}pushInitializers(e,a),pushInitializers(e,n)}(a,e,t),function(e,t,r){if(r.length>0){for(var a=[],n=t,i=t.name,s=r.length-1;s>=0;s--){var o={v:!1};try{var c=r[s](n,{kind:"class",name:i,addInitializer:createAddInitializerMethod(a,o)})}finally{o.v=!0}void 0!==c&&(assertValidReturnValue(10,c),n=c)}e.push(n,function(){for(var e=0;e=0;g--){var y;void 0!==(p=memberDec(v[g],n,c,s,a,i,o,f))&&(assertValidReturnValue(a,p),0===a?y=p:1===a?(y=p.init,d=p.get||f.get,h=p.set||f.set,f={get:d,set:h}):f=p,void 0!==y&&(void 0===l?l=y:"function"==typeof l?l=[l,y]:l.push(y)))}if(0===a||1===a){if(void 0===l)l=function(e,t){return t};else if("function"!=typeof l){var m=l;l=function(e,t){for(var r=t,n=0;n3,h=f>=5;if(h?(l=e,0!=(f-=5)&&(u=n=n||[])):(l=e.prototype,0!==f&&(u=r=r||[])),0!==f&&!d){var v=h?o:i,g=v.get(p)||0;if(!0===g||3===g&&4!==f||4===g&&3!==f)throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: "+p);!g&&f>2?v.set(p,f):v.set(p,!0)}applyMemberDec(a,l,c,p,f,h,d,u)}}return pushInitializers(a,r),pushInitializers(a,n),a}function pushInitializers(e,t){t&&e.push(function(e){for(var r=0;r0){for(var r=[],n=e,a=e.name,i=t.length-1;i>=0;i--){var o={v:!1};try{var s=t[i](n,{kind:"class",name:a,addInitializer:createAddInitializerMethod(r,o)})}finally{o.v=!0}void 0!==s&&(assertValidReturnValue(10,s),n=s)}return[n,function(){for(var e=0;e=0;m--){var b;void 0!==(h=memberDec(g[m],n,u,o,a,i,s,p,c))&&(assertValidReturnValue(a,h),0===a?b=h:1===a?(b=h.init,v=h.get||p.get,y=h.set||p.set,p={get:v,set:y}):p=h,void 0!==b&&(void 0===l?l=b:"function"==typeof l?l=[l,b]:l.push(b)))}if(0===a||1===a){if(void 0===l)l=function(e,t){return t};else if("function"!=typeof l){var I=l;l=function(e,t){for(var r=t,n=0;n3,y=d>=5,g=r;if(y?(f=e,0!=(d-=5)&&(p=a=a||[]),v&&!i&&(i=function(t){return checkInRHS(t)===e}),g=i):(f=e.prototype,0!==d&&(p=n=n||[])),0!==d&&!v){var m=y?c:o,b=m.get(h)||0;if(!0===b||3===b&&4!==d||4===b&&3!==d)throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: "+h);!b&&d>2?m.set(h,d):m.set(h,!0)}applyMemberDec(s,f,l,h,d,y,v,p,g)}}return pushInitializers(s,n),pushInitializers(s,a),s}function pushInitializers(e,t){t&&e.push(function(e){for(var r=0;r0){for(var r=[],n=e,a=e.name,i=t.length-1;i>=0;i--){var s={v:!1};try{var o=t[i](n,{kind:"class",name:a,addInitializer:createAddInitializerMethod(r,s)})}finally{s.v=!0}void 0!==o&&(assertValidReturnValue(10,o),n=o)}return[n,function(){for(var e=0;e=0;j-=r?2:1){var D=v[j],E=r?v[j-1]:void 0,I={},O={kind:["field","accessor","method","getter","setter","class"][o],name:n,metadata:a,addInitializer:function(e,t){if(e.v)throw Error("attempted to call addInitializer after decoration was finished");s(t,"An initializer","be",!0),c.push(t)}.bind(null,I)};try{if(b)(y=s(D.call(E,P,O),"class decorators","return"))&&(P=y);else{var k,F;O.static=l,O.private=f,f?2===o?k=function(e){return m(e),w.value}:(o<4&&(k=i(w,"get",m)),3!==o&&(F=i(w,"set",m))):(k=function(e){return e[n]},(o<2||4===o)&&(F=function(e,t){e[n]=t}));var N=O.access={has:f?h.bind():function(e){return n in e}};if(k&&(N.get=k),F&&(N.set=F),P=D.call(E,d?{get:w.get,set:w.set}:w[A],O),d){if("object"==typeof P&&P)(y=s(P.get,"accessor.get"))&&(w.get=y),(y=s(P.set,"accessor.set"))&&(w.set=y),(y=s(P.init,"accessor.init"))&&S.push(y);else if(void 0!==P)throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0")}else s(P,(p?"field":"method")+" decorators","return")&&(p?S.push(P):w[A]=P)}}finally{I.v=!0}}return(p||d)&&u.push(function(e,t){for(var r=S.length-1;r>=0;r--)t=S[r].call(e,t);return t}),p||b||(f?d?u.push(i(w,"get"),i(w,"set")):u.push(2===o?w[A]:i.call.bind(w[A])):Object.defineProperty(e,n,w)),P}function u(e,t){return Object.defineProperty(e,Symbol.metadata||Symbol.for("Symbol.metadata"),{configurable:!0,enumerable:!0,value:t})}if(arguments.length>=6)var l=a[Symbol.metadata||Symbol.for("Symbol.metadata")];var f=Object.create(null==l?null:l),p=function(e,t,r,n){var o,a,i=[],s=function(t){return checkInRHS(t)===e},u=new Map;function l(e){e&&i.push(c.bind(null,e))}for(var f=0;f3,y=16&d,v=!!(8&d),g=0==(d&=7),b=h+"/"+v;if(!g&&!m){var w=u.get(b);if(!0===w||3===w&&4!==d||4===w&&3!==d)throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: "+h);u.set(b,!(d>2)||d)}applyDec(v?e:e.prototype,p,y,m?"#"+h:toPropertyKey(h),d,n,v?a=a||[]:o=o||[],i,v,m,g,1===d,v&&m?s:r)}}return l(o),l(a),i}(e,t,o,f);return r.length||u(e,f),{e:p,get c(){var t=[];return r.length&&[u(applyDec(e,[r],n,e.name,5,f,t),f),c.bind(null,t,e)]}}}',{globals:["TypeError","Array","Object","Error","Symbol","Map"],locals:{applyDecs2305:["body.0.id"]},exportBindingAssignments:[],exportName:"applyDecs2305",dependencies:{checkInRHS:["body.0.body.body.6.declarations.1.init.callee.body.body.0.declarations.3.init.body.body.0.argument.left.callee"],setFunctionName:["body.0.body.body.3.body.body.2.consequent.body.2.expression.consequent.expressions.0.consequent.right.properties.0.value.callee","body.0.body.body.3.body.body.2.consequent.body.2.expression.consequent.expressions.1.right.callee"],toPropertyKey:["body.0.body.body.6.declarations.1.init.callee.body.body.2.body.body.1.consequent.body.2.expression.arguments.3.alternate.callee"]},internal:!1}),classApplyDescriptorDestructureSet:yj("7.13.10",'function _classApplyDescriptorDestructureSet(e,t){if(t.set)return"__destrObj"in t||(t.__destrObj={set value(r){t.set.call(e,r)}}),t.__destrObj;if(!t.writable)throw new TypeError("attempted to set read only private field");return t}',{globals:["TypeError"],locals:{_classApplyDescriptorDestructureSet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classApplyDescriptorDestructureSet",dependencies:{},internal:!1}),classApplyDescriptorGet:yj("7.13.10","function _classApplyDescriptorGet(e,t){return t.get?t.get.call(e):t.value}",{globals:[],locals:{_classApplyDescriptorGet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classApplyDescriptorGet",dependencies:{},internal:!1}),classApplyDescriptorSet:yj("7.13.10",'function _classApplyDescriptorSet(e,t,l){if(t.set)t.set.call(e,l);else{if(!t.writable)throw new TypeError("attempted to set read only private field");t.value=l}}',{globals:["TypeError"],locals:{_classApplyDescriptorSet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classApplyDescriptorSet",dependencies:{},internal:!1}),classCheckPrivateStaticAccess:yj("7.13.10","function _classCheckPrivateStaticAccess(s,a,r){return assertClassBrand(a,s,r)}",{globals:[],locals:{_classCheckPrivateStaticAccess:["body.0.id"]},exportBindingAssignments:[],exportName:"_classCheckPrivateStaticAccess",dependencies:{assertClassBrand:["body.0.body.body.0.argument.callee"]},internal:!1}),classCheckPrivateStaticFieldDescriptor:yj("7.13.10",'function _classCheckPrivateStaticFieldDescriptor(t,e){if(void 0===t)throw new TypeError("attempted to "+e+" private static field before its declaration")}',{globals:["TypeError"],locals:{_classCheckPrivateStaticFieldDescriptor:["body.0.id"]},exportBindingAssignments:[],exportName:"_classCheckPrivateStaticFieldDescriptor",dependencies:{},internal:!1}),classExtractFieldDescriptor:yj("7.13.10","function _classExtractFieldDescriptor(e,t){return classPrivateFieldGet2(t,e)}",{globals:[],locals:{_classExtractFieldDescriptor:["body.0.id"]},exportBindingAssignments:[],exportName:"_classExtractFieldDescriptor",dependencies:{classPrivateFieldGet2:["body.0.body.body.0.argument.callee"]},internal:!1}),classPrivateFieldDestructureSet:yj("7.4.4","function _classPrivateFieldDestructureSet(e,t){var r=classPrivateFieldGet2(t,e);return classApplyDescriptorDestructureSet(e,r)}",{globals:[],locals:{_classPrivateFieldDestructureSet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classPrivateFieldDestructureSet",dependencies:{classApplyDescriptorDestructureSet:["body.0.body.body.1.argument.callee"],classPrivateFieldGet2:["body.0.body.body.0.declarations.0.init.callee"]},internal:!1}),classPrivateFieldGet:yj("7.0.0-beta.0","function _classPrivateFieldGet(e,t){var r=classPrivateFieldGet2(t,e);return classApplyDescriptorGet(e,r)}",{globals:[],locals:{_classPrivateFieldGet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classPrivateFieldGet",dependencies:{classApplyDescriptorGet:["body.0.body.body.1.argument.callee"],classPrivateFieldGet2:["body.0.body.body.0.declarations.0.init.callee"]},internal:!1}),classPrivateFieldSet:yj("7.0.0-beta.0","function _classPrivateFieldSet(e,t,r){var s=classPrivateFieldGet2(t,e);return classApplyDescriptorSet(e,s,r),r}",{globals:[],locals:{_classPrivateFieldSet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classPrivateFieldSet",dependencies:{classApplyDescriptorSet:["body.0.body.body.1.argument.expressions.0.callee"],classPrivateFieldGet2:["body.0.body.body.0.declarations.0.init.callee"]},internal:!1}),classPrivateMethodGet:yj("7.1.6","function _classPrivateMethodGet(s,a,r){return assertClassBrand(a,s),r}",{globals:[],locals:{_classPrivateMethodGet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classPrivateMethodGet",dependencies:{assertClassBrand:["body.0.body.body.0.argument.expressions.0.callee"]},internal:!1}),classPrivateMethodSet:yj("7.1.6",'function _classPrivateMethodSet(){throw new TypeError("attempted to reassign private method")}',{globals:["TypeError"],locals:{_classPrivateMethodSet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classPrivateMethodSet",dependencies:{},internal:!1}),classStaticPrivateFieldDestructureSet:yj("7.13.10",'function _classStaticPrivateFieldDestructureSet(t,r,s){return assertClassBrand(r,t),classCheckPrivateStaticFieldDescriptor(s,"set"),classApplyDescriptorDestructureSet(t,s)}',{globals:[],locals:{_classStaticPrivateFieldDestructureSet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classStaticPrivateFieldDestructureSet",dependencies:{classApplyDescriptorDestructureSet:["body.0.body.body.0.argument.expressions.2.callee"],assertClassBrand:["body.0.body.body.0.argument.expressions.0.callee"],classCheckPrivateStaticFieldDescriptor:["body.0.body.body.0.argument.expressions.1.callee"]},internal:!1}),classStaticPrivateFieldSpecGet:yj("7.0.2",'function _classStaticPrivateFieldSpecGet(t,s,r){return assertClassBrand(s,t),classCheckPrivateStaticFieldDescriptor(r,"get"),classApplyDescriptorGet(t,r)}',{globals:[],locals:{_classStaticPrivateFieldSpecGet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classStaticPrivateFieldSpecGet",dependencies:{classApplyDescriptorGet:["body.0.body.body.0.argument.expressions.2.callee"],assertClassBrand:["body.0.body.body.0.argument.expressions.0.callee"],classCheckPrivateStaticFieldDescriptor:["body.0.body.body.0.argument.expressions.1.callee"]},internal:!1}),classStaticPrivateFieldSpecSet:yj("7.0.2",'function _classStaticPrivateFieldSpecSet(s,t,r,e){return assertClassBrand(t,s),classCheckPrivateStaticFieldDescriptor(r,"set"),classApplyDescriptorSet(s,r,e),e}',{globals:[],locals:{_classStaticPrivateFieldSpecSet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classStaticPrivateFieldSpecSet",dependencies:{classApplyDescriptorSet:["body.0.body.body.0.argument.expressions.2.callee"],assertClassBrand:["body.0.body.body.0.argument.expressions.0.callee"],classCheckPrivateStaticFieldDescriptor:["body.0.body.body.0.argument.expressions.1.callee"]},internal:!1}),classStaticPrivateMethodSet:yj("7.3.2",'function _classStaticPrivateMethodSet(){throw new TypeError("attempted to set read only static private field")}',{globals:["TypeError"],locals:{_classStaticPrivateMethodSet:["body.0.id"]},exportBindingAssignments:[],exportName:"_classStaticPrivateMethodSet",dependencies:{},internal:!1}),defineEnumerableProperties:yj("7.0.0-beta.0",'function _defineEnumerableProperties(e,r){for(var t in r){var n=r[t];n.configurable=n.enumerable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,t,n)}if(Object.getOwnPropertySymbols)for(var a=Object.getOwnPropertySymbols(r),b=0;b0;)try{var o=r.pop(),p=o.d.call(o.v);if(o.a)return Promise.resolve(p).then(next,err)}catch(r){return err(r)}if(s)throw e}function err(r){return e=s?new dispose_SuppressedError(e,r):r,s=!0,next()}return next()}',{globals:["SuppressedError","Error","Object","Promise"],locals:{dispose_SuppressedError:["body.0.id","body.0.body.body.0.argument.expressions.0.alternate.expressions.1.left.object","body.0.body.body.0.argument.expressions.0.alternate.expressions.1.right.arguments.1.properties.0.value.properties.0.value","body.0.body.body.0.argument.expressions.1.callee","body.1.body.body.1.body.body.0.argument.expressions.0.right.consequent.callee","body.0.body.body.0.argument.expressions.0.consequent.left","body.0.body.body.0.argument.expressions.0.alternate.expressions.0.left"],_dispose:["body.1.id"]},exportBindingAssignments:[],exportName:"_dispose",dependencies:{},internal:!1}),objectSpread:yj("7.0.0-beta.0",'function _objectSpread(e){for(var r=1;r0;)e=e[n],n=a.shift();if(!(arguments.length>2))return e[n];e[n]=r}catch(e){throw e.message+=" (when accessing "+t+")",e}}var vj=Object.create(null);function Rj(e){if(!vj[e]){var t=mj[e];if(!t)throw Object.assign(new ReferenceError("Unknown helper "+e),{code:"BABEL_HELPER_UNKNOWN",helper:e});vj[e]={minVersion:t.minVersion,build:function(e,r,a,n){var s=t.ast();return function(e,t,r,a,n,s){var o=t.locals,d=t.dependencies,c=t.exportBindingAssignments,l=t.exportName,u=new Set(a||[]);r&&u.add(r);for(var p=0,f=(Object.entries||function(e){return Object.keys(e).map(function(t){return[t,e[t]]})})(o);p=1.5*r;return Math.round(e/r)+" "+a+(n?"s":"")}return Sj=function(i,d){d=d||{};var c=typeof i;if("string"===c&&i.length>0)return function(o){if((o=String(o)).length>100)return;var i=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(o);if(!i)return;var d=parseFloat(i[1]);switch((i[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return d*s;case"weeks":case"week":case"w":return d*n;case"days":case"day":case"d":return d*a;case"hours":case"hour":case"hrs":case"hr":case"h":return d*r;case"minutes":case"minute":case"mins":case"min":case"m":return d*t;case"seconds":case"second":case"secs":case"sec":case"s":return d*e;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return d;default:return}}(i);if("number"===c&&isFinite(i))return d.long?function(n){var s=Math.abs(n);if(s>=a)return o(n,s,a,"day");if(s>=r)return o(n,s,r,"hour");if(s>=t)return o(n,s,t,"minute");if(s>=e)return o(n,s,e,"second");return n+" ms"}(i):function(n){var s=Math.abs(n);if(s>=a)return Math.round(n/a)+"d";if(s>=r)return Math.round(n/r)+"h";if(s>=t)return Math.round(n/t)+"m";if(s>=e)return Math.round(n/e)+"s";return n+"ms"}(i);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(i))},Sj}var _j=function(e){function t(e){var a,n,s,o=null;function i(){for(var e=arguments.length,r=new Array(e),n=0;n=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)},t.storage=function(){try{return localStorage}catch(e){}}(),t.destroy=(r=!1,function(){r||(r=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}),t.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"],t.log=console.debug||console.log||function(){},e.exports=_j(t),e.exports.formatters.j=function(e){try{return JSON.stringify(e)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}}(kj,kj.exports);var Ij=kj.exports,Dj=Um,Nj=Wm,Oj=hr,Bj=tr,Mj=vr,Fj=se,Lj=ir,Uj=de,qj=Ge,Gj=He,Wj=kt,Vj=Ct,Hj=me,Kj=je,zj=Vm,Xj=Hm,Jj=nr,Yj=Jm,$j=ke,Qj=qe,Zj=Ym.isCompatTag;e.isExistentialTypeParam=function(){throw new Error("`path.isExistentialTypeParam` has been renamed to `path.isExistsTypeAnnotation()` in Babel 7.")},e.isNumericLiteralTypeAnnotation=function(){throw new Error("`path.isNumericLiteralTypeAnnotation()` has been renamed to `path.isNumberLiteralTypeAnnotation()` in Babel 7.")};var ew=Object.freeze({__proto__:null,isBindingIdentifier:function(){var e=this.node,t=this.parent,r=this.parentPath.parent;return Uj(e)&&Dj(e,t,r)},isBlockScoped:function(){return Nj(this.node)},isExpression:function(){return this.isIdentifier()?this.isReferencedIdentifier():Bj(this.node)},isFlow:function(){var e=this.node;return!!Mj(e)||(qj(e)?"type"===e.importKind||"typeof"===e.importKind:Oj(e)?"type"===e.exportKind:!!Gj(e)&&("type"===e.importKind||"typeof"===e.importKind))},isForAwaitStatement:function(){return Qj(this.node,{await:!0})},isGenerated:function(){return!this.isUser()},isPure:function(e){return this.scope.isPure(this.node,e)},isReferenced:function(){return zj(this.node,this.parent)},isReferencedIdentifier:function(e){var t=this.node,r=this.parent;if(!Uj(t,e)&&!Vj(r,e)){if(!Wj(t,e))return!1;if(Zj(t.name))return!1}return zj(t,r,this.parentPath.parent)},isReferencedMemberExpression:function(){var e=this.node,t=this.parent;return Hj(e)&&zj(e,t)},isRestProperty:function(){var e;return Kj(this.node)&&(null==(e=this.parentPath)?void 0:e.isObjectPattern())},isScope:function(){return Xj(this.node,this.parent)},isSpreadProperty:function(){var e;return Kj(this.node)&&(null==(e=this.parentPath)?void 0:e.isObjectExpression())},isStatement:function(){var e=this.node,t=this.parent;if(Jj(e)){if($j(e)){if(Lj(t,{left:e}))return!1;if(Fj(t,{init:e}))return!1}return!0}return!1},isUser:function(){return this.node&&!!this.node.loc},isVar:function(){return Yj(this.node)}}),tw=Ca,rw=Hn,aw=Pa,nw=ts,sw=J;function ow(e){return e in Aj}function iw(e){return null==e?void 0:e._exploded}function dw(e){if(iw(e))return e;e._exploded=!0;for(var t=0,r=Object.keys(e);t=11?t+=r-1:r>=9?t+=r-9:r>=1&&(t+=r+1),r++}while(this.hasLabel(t)||this.hasBinding(t)||this.hasGlobal(t)||this.hasReference(t));var a=this.getProgramParent();return a.references[t]=!0,a.uids[t]=!0,t},t.generateUidBasedOnNode=function(e,t){var r=[];TE(e,r);var a=r.join("$");return a=a.replace(/^_/,"")||t||"ref",this.generateUid(a.slice(0,20))},t.generateUidIdentifierBasedOnNode=function(e,t){return Bw(this.generateUidBasedOnNode(e,t))},t.isStatic=function(e){if(iE(e)||nE(e)||vE(e))return!0;if(zw(e)){var t=this.getBinding(e.name);return t?t.constant:this.hasBinding(e.name)}return!1},t.maybeGenerateMemoised=function(e,t){if(this.isStatic(e))return null;var r=this.generateUidIdentifierBasedOnNode(e);return t?r:(this.push({id:r}),Nw(r))},t.checkBlockScopedCollisions=function(e,t,r,a){if("param"!==t&&("local"!==e.kind&&("let"===t||"let"===e.kind||"const"===e.kind||"module"===e.kind||"param"===e.kind&&"const"===t)))throw this.path.hub.buildError(a,'Duplicate declaration "'+r+'"',TypeError)},t.rename=function(e,t){var r=this.getBinding(e);r&&(t||(t=this.generateUidIdentifier(e).name),new jw(r,e,t).rename(arguments[2]))},t.dump=function(){var e="-".repeat(60);console.log(e);var t=this;do{console.log("#",t.block.type);for(var r=0,a=Object.keys(t.bindings);r0)&&this.isPure(e.body,t));if(qw(e)){for(var o,d=i(e.body);!(o=d()).done;){var c=o.value;if(!this.isPure(c,t))return!1}return!0}if(Fw(e))return this.isPure(e.left,t)&&this.isPure(e.right,t);if(Mw(e)||bE(e)){for(var l,u=i(e.elements);!(l=u()).done;){var p=l.value;if(null!==p&&!this.isPure(p,t))return!1}return!0}if(eE(e)||hE(e)){for(var f,g=i(e.properties);!(f=g()).done;){var y=f.value;if(!this.isPure(y,t))return!1}return!0}if($w(e))return!(e.computed&&!this.isPure(e.key,t))&&!((null==(n=e.decorators)?void 0:n.length)>0);if(tE(e))return!(e.computed&&!this.isPure(e.key,t))&&(!((null==(s=e.decorators)?void 0:s.length)>0)&&!((xE(e)||e.static)&&null!==e.value&&!this.isPure(e.value,t)));if(dE(e))return this.isPure(e.argument,t);if(oE(e)){for(var m,h=i(e.expressions);!(m=h()).done;){var b=m.value;if(!this.isPure(b,t))return!1}return!0}return sE(e)?uE(e.tag,"String.raw")&&!this.hasBinding("String",{noGlobals:!0})&&this.isPure(e.quasi,t):Yw(e)?!e.computed&&zw(e.object)&&"Symbol"===e.object.name&&zw(e.property)&&"for"!==e.property.name&&!this.hasBinding("Symbol",{noGlobals:!0}):Lw(e)?uE(e.callee,"Symbol.for")&&!this.hasBinding("Symbol",{noGlobals:!0})&&1===e.arguments.length&&ue(e.arguments[0]):rE(e)},t.setData=function(e,t){return this.data[e]=t},t.getData=function(e){var t=this;do{var r=t.data[e];if(null!=r)return r}while(t=t.parent)},t.removeData=function(e){var t=this;do{null!=t.data[e]&&(t.data[e]=null)}while(t=t.parent)},t.init=function(){this.inited||(this.inited=!0,this.crawl())},t.crawl=function(){var e=this.path;PE(this),this.data=Object.create(null);var t=this;do{if(t.crawling)return;if(t.path.isProgram())break}while(t=t.parent);var r=t,a={references:[],constantViolations:[],assignments:[]};if(this.crawling=!0,AE||(AE=UN.visitors.merge([{Scope:function(e){PE(e.scope)}},CE])),"Program"!==e.type){for(var n,s=i(AE.enter);!(n=s()).done;){n.value.call(a,e,a)}var o=AE[e.type];if(o)for(var d,c=i(o.enter);!(d=c()).done;){d.value.call(a,e,a)}}e.traverse(AE,a),this.crawling=!1;for(var l,u=i(a.assignments);!(l=u()).done;){for(var p=l.value,f=p.getAssignmentIdentifiers(),g=0,y=Object.keys(f);g1&&(r+=t),"_"+r},IE.prototype.toArray=function(e,t,r){if(zw(e)){var a=this.getBinding(e.name);if(null!=a&&a.constant&&a.path.isGenericType("Array"))return e}if(Mw(e))return e;if(zw(e,{name:"arguments"}))return Dw(pE(pE(pE(Bw("Array"),Bw("prototype")),Bw("slice")),Bw("call")),[e]);var n,s=[e];return!0===t?n="toConsumableArray":"number"==typeof t?(s.push(fE(t)),n="slicedToArray"):n="toArray",r&&(s.unshift(this.path.hub.addHelper(n)),n="maybeArrayLike"),Dw(this.path.hub.addHelper(n),s)},IE.prototype.getAllBindingsOfKind=function(){for(var e=Object.create(null),t=arguments.length,r=new Array(t),a=0;a>18&63]+DE[e>>12&63]+DE[e>>6&63]+DE[63&e]}function LE(e,t,r){for(var a,n=[],s=t;sd?d:i+o));return 1===a?(t=e[r-1],n+=DE[t>>2],n+=DE[t<<4&63],n+="=="):2===a&&(t=(e[r-2]<<8)+e[r-1],n+=DE[t>>10],n+=DE[t>>4&63],n+=DE[t<<2&63],n+="="),s.push(n),s.join("")}function qE(e,t,r,a,n){var s,o,i=8*n-a-1,d=(1<>1,l=-7,u=r?n-1:0,p=r?-1:1,f=e[t+u];for(u+=p,s=f&(1<<-l)-1,f>>=-l,l+=i;l>0;s=256*s+e[t+u],u+=p,l-=8);for(o=s&(1<<-l)-1,s>>=-l,l+=a;l>0;o=256*o+e[t+u],u+=p,l-=8);if(0===s)s=1-c;else{if(s===d)return o?NaN:1/0*(f?-1:1);o+=Math.pow(2,a),s-=c}return(f?-1:1)*o*Math.pow(2,s-a)}function GE(e,t,r,a,n,s){var o,i,d,c=8*s-n-1,l=(1<>1,p=23===n?Math.pow(2,-24)-Math.pow(2,-77):0,f=a?0:s-1,g=a?1:-1,y=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(i=isNaN(t)?1:0,o=l):(o=Math.floor(Math.log(t)/Math.LN2),t*(d=Math.pow(2,-o))<1&&(o--,d*=2),(t+=o+u>=1?p/d:p*Math.pow(2,1-u))*d>=2&&(o++,d/=2),o+u>=l?(i=0,o=l):o+u>=1?(i=(t*d-1)*Math.pow(2,n),o+=u):(i=t*Math.pow(2,u-1)*Math.pow(2,n),o=0));n>=8;e[r+f]=255&i,f+=g,i/=256,n-=8);for(o=o<0;e[r+f]=255&o,f+=g,o/=256,c-=8);e[r+f-g]|=128*y}var WE={}.toString,VE=Array.isArray||function(e){return"[object Array]"==WE.call(e)};function HE(){return zE.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function KE(e,t){if(HE()=HE())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+HE().toString(16)+" bytes");return 0|e}function ZE(e){return!(null==e||!e._isBuffer)}function eS(e,t){if(ZE(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var r=e.length;if(0===r)return 0;for(var a=!1;;)switch(t){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":case void 0:return PS(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return AS(e).length;default:if(a)return PS(e).length;t=(""+t).toLowerCase(),a=!0}}function tS(e,t,r){var a=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return mS(this,t,r);case"utf8":case"utf-8":return pS(this,t,r);case"ascii":return gS(this,t,r);case"latin1":case"binary":return yS(this,t,r);case"base64":return uS(this,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return hS(this,t,r);default:if(a)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),a=!0}}function rS(e,t,r){var a=e[t];e[t]=e[r],e[r]=a}function aS(e,t,r,a,n){if(0===e.length)return-1;if("string"==typeof r?(a=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),r=+r,isNaN(r)&&(r=n?0:e.length-1),r<0&&(r=e.length+r),r>=e.length){if(n)return-1;r=e.length-1}else if(r<0){if(!n)return-1;r=0}if("string"==typeof t&&(t=zE.from(t,a)),ZE(t))return 0===t.length?-1:nS(e,t,r,a,n);if("number"==typeof t)return t&=255,zE.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?n?Uint8Array.prototype.indexOf.call(e,t,r):Uint8Array.prototype.lastIndexOf.call(e,t,r):nS(e,[t],r,a,n);throw new TypeError("val must be string, number or Buffer")}function nS(e,t,r,a,n){var s,o=1,i=e.length,d=t.length;if(void 0!==a&&("ucs2"===(a=String(a).toLowerCase())||"ucs-2"===a||"utf16le"===a||"utf-16le"===a)){if(e.length<2||t.length<2)return-1;o=2,i/=2,d/=2,r/=2}function c(e,t){return 1===o?e[t]:e.readUInt16BE(t*o)}if(n){var l=-1;for(s=r;si&&(r=i-d),s=r;s>=0;s--){for(var u=!0,p=0;pn&&(a=n):a=n;var s=t.length;if(s%2!=0)throw new TypeError("Invalid hex string");a>s/2&&(a=s/2);for(var o=0;o>8,n=r%256,s.push(n),s.push(a);return s}(t,e.length-r),e,r,a)}function uS(e,t,r){return 0===t&&r===e.length?UE(e):UE(e.slice(t,r))}function pS(e,t,r){r=Math.min(e.length,r);for(var a=[],n=t;n239?4:c>223?3:c>191?2:1;if(n+u<=r)switch(u){case 1:c<128&&(l=c);break;case 2:128==(192&(s=e[n+1]))&&(d=(31&c)<<6|63&s)>127&&(l=d);break;case 3:s=e[n+1],o=e[n+2],128==(192&s)&&128==(192&o)&&(d=(15&c)<<12|(63&s)<<6|63&o)>2047&&(d<55296||d>57343)&&(l=d);break;case 4:s=e[n+1],o=e[n+2],i=e[n+3],128==(192&s)&&128==(192&o)&&128==(192&i)&&(d=(15&c)<<18|(63&s)<<12|(63&o)<<6|63&i)>65535&&d<1114112&&(l=d)}null===l?(l=65533,u=1):l>65535&&(l-=65536,a.push(l>>>10&1023|55296),l=56320|1023&l),a.push(l),n+=u}return function(e){var t=e.length;if(t<=fS)return String.fromCharCode.apply(String,e);var r="",a=0;for(;a0&&(e=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(e+=" ... ")),""},zE.prototype.compare=function(e,t,r,a,n){if(!ZE(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===r&&(r=e?e.length:0),void 0===a&&(a=0),void 0===n&&(n=this.length),t<0||r>e.length||a<0||n>this.length)throw new RangeError("out of range index");if(a>=n&&t>=r)return 0;if(a>=n)return-1;if(t>=r)return 1;if(this===e)return 0;for(var s=(n>>>=0)-(a>>>=0),o=(r>>>=0)-(t>>>=0),i=Math.min(s,o),d=this.slice(a,n),c=e.slice(t,r),l=0;ln)&&(r=n),e.length>0&&(r<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");a||(a="utf8");for(var s=!1;;)switch(a){case"hex":return sS(this,e,t,r);case"utf8":case"utf-8":return oS(this,e,t,r);case"ascii":return iS(this,e,t,r);case"latin1":case"binary":return dS(this,e,t,r);case"base64":return cS(this,e,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return lS(this,e,t,r);default:if(s)throw new TypeError("Unknown encoding: "+a);a=(""+a).toLowerCase(),s=!0}},zE.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var fS=4096;function gS(e,t,r){var a="";r=Math.min(e.length,r);for(var n=t;na)&&(r=a);for(var n="",s=t;sr)throw new RangeError("Trying to access beyond buffer length")}function xS(e,t,r,a,n,s){if(!ZE(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>n||te.length)throw new RangeError("Index out of range")}function vS(e,t,r,a){t<0&&(t=65535+t+1);for(var n=0,s=Math.min(e.length-r,2);n>>8*(a?n:1-n)}function RS(e,t,r,a){t<0&&(t=4294967295+t+1);for(var n=0,s=Math.min(e.length-r,4);n>>8*(a?n:3-n)&255}function jS(e,t,r,a,n,s){if(r+a>e.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function wS(e,t,r,a,n){return n||jS(e,0,r,4),GE(e,t,r,a,23,4),r+4}function ES(e,t,r,a,n){return n||jS(e,0,r,8),GE(e,t,r,a,52,8),r+8}zE.prototype.slice=function(e,t){var r,a=this.length;if((e=~~e)<0?(e+=a)<0&&(e=0):e>a&&(e=a),(t=void 0===t?a:~~t)<0?(t+=a)<0&&(t=0):t>a&&(t=a),t0&&(n*=256);)a+=this[e+--t]*n;return a},zE.prototype.readUInt8=function(e,t){return t||bS(e,1,this.length),this[e]},zE.prototype.readUInt16LE=function(e,t){return t||bS(e,2,this.length),this[e]|this[e+1]<<8},zE.prototype.readUInt16BE=function(e,t){return t||bS(e,2,this.length),this[e]<<8|this[e+1]},zE.prototype.readUInt32LE=function(e,t){return t||bS(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},zE.prototype.readUInt32BE=function(e,t){return t||bS(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},zE.prototype.readIntLE=function(e,t,r){e|=0,t|=0,r||bS(e,t,this.length);for(var a=this[e],n=1,s=0;++s=(n*=128)&&(a-=Math.pow(2,8*t)),a},zE.prototype.readIntBE=function(e,t,r){e|=0,t|=0,r||bS(e,t,this.length);for(var a=t,n=1,s=this[e+--a];a>0&&(n*=256);)s+=this[e+--a]*n;return s>=(n*=128)&&(s-=Math.pow(2,8*t)),s},zE.prototype.readInt8=function(e,t){return t||bS(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},zE.prototype.readInt16LE=function(e,t){t||bS(e,2,this.length);var r=this[e]|this[e+1]<<8;return 32768&r?4294901760|r:r},zE.prototype.readInt16BE=function(e,t){t||bS(e,2,this.length);var r=this[e+1]|this[e]<<8;return 32768&r?4294901760|r:r},zE.prototype.readInt32LE=function(e,t){return t||bS(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},zE.prototype.readInt32BE=function(e,t){return t||bS(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},zE.prototype.readFloatLE=function(e,t){return t||bS(e,4,this.length),qE(this,e,!0,23,4)},zE.prototype.readFloatBE=function(e,t){return t||bS(e,4,this.length),qE(this,e,!1,23,4)},zE.prototype.readDoubleLE=function(e,t){return t||bS(e,8,this.length),qE(this,e,!0,52,8)},zE.prototype.readDoubleBE=function(e,t){return t||bS(e,8,this.length),qE(this,e,!1,52,8)},zE.prototype.writeUIntLE=function(e,t,r,a){(e=+e,t|=0,r|=0,a)||xS(this,e,t,r,Math.pow(2,8*r)-1,0);var n=1,s=0;for(this[t]=255&e;++s=0&&(s*=256);)this[t+n]=e/s&255;return t+r},zE.prototype.writeUInt8=function(e,t,r){return e=+e,t|=0,r||xS(this,e,t,1,255,0),zE.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},zE.prototype.writeUInt16LE=function(e,t,r){return e=+e,t|=0,r||xS(this,e,t,2,65535,0),zE.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):vS(this,e,t,!0),t+2},zE.prototype.writeUInt16BE=function(e,t,r){return e=+e,t|=0,r||xS(this,e,t,2,65535,0),zE.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):vS(this,e,t,!1),t+2},zE.prototype.writeUInt32LE=function(e,t,r){return e=+e,t|=0,r||xS(this,e,t,4,4294967295,0),zE.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):RS(this,e,t,!0),t+4},zE.prototype.writeUInt32BE=function(e,t,r){return e=+e,t|=0,r||xS(this,e,t,4,4294967295,0),zE.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):RS(this,e,t,!1),t+4},zE.prototype.writeIntLE=function(e,t,r,a){if(e=+e,t|=0,!a){var n=Math.pow(2,8*r-1);xS(this,e,t,r,n-1,-n)}var s=0,o=1,i=0;for(this[t]=255&e;++s=0&&(o*=256);)e<0&&0===i&&0!==this[t+s+1]&&(i=1),this[t+s]=(e/o|0)-i&255;return t+r},zE.prototype.writeInt8=function(e,t,r){return e=+e,t|=0,r||xS(this,e,t,1,127,-128),zE.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},zE.prototype.writeInt16LE=function(e,t,r){return e=+e,t|=0,r||xS(this,e,t,2,32767,-32768),zE.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):vS(this,e,t,!0),t+2},zE.prototype.writeInt16BE=function(e,t,r){return e=+e,t|=0,r||xS(this,e,t,2,32767,-32768),zE.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):vS(this,e,t,!1),t+2},zE.prototype.writeInt32LE=function(e,t,r){return e=+e,t|=0,r||xS(this,e,t,4,2147483647,-2147483648),zE.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):RS(this,e,t,!0),t+4},zE.prototype.writeInt32BE=function(e,t,r){return e=+e,t|=0,r||xS(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),zE.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):RS(this,e,t,!1),t+4},zE.prototype.writeFloatLE=function(e,t,r){return wS(this,e,t,!0,r)},zE.prototype.writeFloatBE=function(e,t,r){return wS(this,e,t,!1,r)},zE.prototype.writeDoubleLE=function(e,t,r){return ES(this,e,t,!0,r)},zE.prototype.writeDoubleBE=function(e,t,r){return ES(this,e,t,!1,r)},zE.prototype.copy=function(e,t,r,a){if(r||(r=0),a||0===a||(a=this.length),t>=e.length&&(t=e.length),t||(t=0),a>0&&a=this.length)throw new RangeError("sourceStart out of bounds");if(a<0)throw new RangeError("sourceEnd out of bounds");a>this.length&&(a=this.length),e.length-t=0;--n)e[n+t]=this[n+r];else if(s<1e3||!zE.TYPED_ARRAY_SUPPORT)for(n=0;n>>=0,r=void 0===r?this.length:r>>>0,e||(e=0),"number"==typeof e)for(s=t;s55295&&r<57344){if(!n){if(r>56319){(t-=3)>-1&&s.push(239,191,189);continue}if(o+1===a){(t-=3)>-1&&s.push(239,191,189);continue}n=r;continue}if(r<56320){(t-=3)>-1&&s.push(239,191,189),n=r;continue}r=65536+(n-55296<<10|r-56320)}else n&&(t-=3)>-1&&s.push(239,191,189);if(n=null,r<128){if((t-=1)<0)break;s.push(r)}else if(r<2048){if((t-=2)<0)break;s.push(r>>6|192,63&r|128)}else if(r<65536){if((t-=3)<0)break;s.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;s.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return s}function AS(e){return function(e){var t,r,a,n,s,o;BE||ME();var i=e.length;if(i%4>0)throw new Error("Invalid string. Length must be a multiple of 4");s="="===e[i-2]?2:"="===e[i-1]?1:0,o=new OE(3*i/4-s),a=s>0?i-4:i;var d=0;for(t=0,r=0;t>16&255,o[d++]=n>>8&255,o[d++]=255&n;return 2===s?(n=NE[e.charCodeAt(t)]<<2|NE[e.charCodeAt(t+1)]>>4,o[d++]=255&n):1===s&&(n=NE[e.charCodeAt(t)]<<10|NE[e.charCodeAt(t+1)]<<4|NE[e.charCodeAt(t+2)]>>2,o[d++]=n>>8&255,o[d++]=255&n),o}(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(SS,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function kS(e,t,r,a){for(var n=0;n=t.length||n>=e.length);++n)t[n+r]=e[n];return n}function CS(e){return null!=e&&(!!e._isBuffer||_S(e)||function(e){return"function"==typeof e.readFloatLE&&"function"==typeof e.slice&&_S(e.slice(0,0))}(e))}function _S(e){return!!e.constructor&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}for(var IS=",".charCodeAt(0),DS=";".charCodeAt(0),NS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",OS=new Uint8Array(64),BS=new Uint8Array(128),MS=0;MS<64;MS++){var FS=NS.charCodeAt(MS);OS[MS]=FS,BS[FS]=MS}function LS(e,t){var r=0,a=0,n=0;do{var s=e.next();r|=(31&(n=BS[s]))<>>=1,o&&(r=-2147483648|-r),t+r}function US(e,t,r){var a=t-r;a=a<0?-a<<1|1:a<<1;do{var n=31&a;(a>>>=5)>0&&(n|=32),e.write(OS[n])}while(a>0);return t}function qS(e,t){return!(e.pos>=t)&&e.peek()!==IS}var GS="undefined"!=typeof TextDecoder?new TextDecoder:void 0!==zE?{decode:function(e){return zE.from(e.buffer,e.byteOffset,e.byteLength).toString()}}:{decode:function(e){for(var t="",r=0;r0?t+GS.decode(e.subarray(0,r)):t},o(e)}(),VS=function(){function e(e){this.pos=0,this.buffer=e}var t=e.prototype;return t.next=function(){return this.buffer.charCodeAt(this.pos++)},t.peek=function(){return this.buffer.charCodeAt(this.pos)},t.indexOf=function(e){var t=this.buffer,r=this.pos,a=t.indexOf(e,r);return-1===a?t.length:a},o(e)}();function HS(e){e.sort(KS)}function KS(e,t){return e[0]-t[0]}function zS(e){for(var t=new WS,r=0,a=0,n=0,s=0,o=0;o0&&t.write(DS),0!==i.length)for(var d=0,c=0;c0&&t.write(IS),d=US(t,l[0],d),1!==l.length&&(r=US(t,l[1],r),a=US(t,l[2],a),n=US(t,l[3],n),4!==l.length&&(s=US(t,l[4],s)))}}return t.flush()}var XS=/^[\w+.-]+:\/\//,JS=/^([\w+.-]+:)\/\/([^@/#?]*@)?([^:/#?]*)(:\d+)?(\/[^#?]*)?(\?[^#]*)?(#.*)?/,YS=/^file:(?:\/\/((?![a-z]:)[^/#?]*)?)?(\/?[^#?]*)(\?[^#]*)?(#.*)?/i;function $S(e){return e.startsWith("/")}function QS(e){return/^[.?#]/.test(e)}function ZS(e){var t=JS.exec(e);return eT(t[1],t[2]||"",t[3],t[4]||"",t[5]||"/",t[6]||"",t[7]||"")}function eT(e,t,r,a,n,s,o){return{scheme:e,user:t,host:r,port:a,path:n,query:s,hash:o,type:7}}function tT(e){if(function(e){return e.startsWith("//")}(e)){var t=ZS("http:"+e);return t.scheme="",t.type=6,t}if($S(e)){var r=ZS("http://foo.com"+e);return r.scheme="",r.host="",r.type=5,r}if(function(e){return e.startsWith("file:")}(e))return function(e){var t=YS.exec(e),r=t[2];return eT("file:","",t[1]||"","",$S(r)?r:"/"+r,t[3]||"",t[4]||"")}(e);if(function(e){return XS.test(e)}(e))return ZS(e);var a=ZS("http://foo.com/"+e);return a.scheme="",a.host="",a.type=e?e.startsWith("?")?3:e.startsWith("#")?2:4:1,a}function rT(e,t){for(var r=t<=4,a=e.path.split("/"),n=1,s=0,o=!1,i=1;ia&&(a=s)}rT(r,a);var o=r.query+r.hash;switch(a){case 2:case 3:return o;case 4:var i=r.path.slice(1);return i?QS(t||e)&&!QS(i)?"./"+i+o:i+o:o||".";case 5:return r.path+o;default:return r.scheme+"//"+r.user+r.host+r.port+r.path+o}}function nT(e,t){for(var r=t;r=0&&e[a][0]===t;r=a--);return r}function uT(e,t,r,a){var n=r.lastKey,s=r.lastNeedle,o=r.lastIndex,i=0,d=e.length-1;if(a===n){if(t===s)return dT=-1!==o&&e[o][0]===t,o;t>=s?i=-1===o?0:o:d=o}return r.lastKey=a,r.lastNeedle=t,r.lastIndex=function(e,t,r,a){for(;r<=a;){var n=r+(a-r>>1),s=e[n][0]-t;if(0===s)return dT=!0,n;s<0?r=n+1:a=n-1}return dT=!1,r-1}(e,t,i,d)}var pT=o(function(e,t){var r="string"==typeof e;if(!r&&e._decodedMemo)return e;var a=function(e){return"string"==typeof e?JSON.parse(e):e}(e),n=a.version,s=a.file,o=a.names,i=a.sourceRoot,d=a.sources,c=a.sourcesContent;this.version=n,this.file=s,this.names=o||[],this.sourceRoot=i,this.sources=d,this.sourcesContent=c,this.ignoreList=a.ignoreList||a.x_google_ignoreList||void 0;var l=function(e,t){var r=function(e){if(!e)return"";var t=e.lastIndexOf("/");return e.slice(0,t+1)}(e),a=t?t+"/":"";return function(e){return aT(a+(e||""),r)}}(t,i);this.resolvedSources=d.map(l);var u=a.mappings;if("string"==typeof u)this._encoded=u,this._decoded=void 0;else{if(!Array.isArray(u))throw a.sections?new Error("TraceMap passed sectioned source map, please use FlattenMap export instead"):new Error("invalid source map: "+JSON.stringify(a));this._encoded=void 0,this._decoded=function(e,t){var r=nT(e,0);if(r===e.length)return e;t||(e=e.slice());for(var a=r;a=s.length)return yT(null,null,null,null);var o=s[r],i=mT(o,e._decodedMemo,r,a,n||1);if(-1===i)return yT(null,null,null,null);var d=o[i];if(1===d.length)return yT(null,null,null,null);var c=e.names;return yT(e.resolvedSources[d[1]],d[2]+1,d[3],5===d.length?c[d[4]]:null)}function yT(e,t,r,a){return{source:e,line:t,column:r,name:a}}function mT(e,t,r,a,n){var s=uT(e,a,t,r);return dT?s=(-1===n?cT:lT)(e,a,s):-1===n&&s++,-1===s||s===e.length?-1:s}var hT=o(function(){this._indexes={__proto__:null},this.array=[]});function bT(e,t){var r=function(e,t){return e._indexes[t]}(e,t);if(void 0!==r)return r;var a=e,n=a.array,s=a._indexes,o=n.push(t);return s[t]=o-1}var xT=o(function(e){var t=void 0===e?{}:e,r=t.file,a=t.sourceRoot;this._names=new hT,this._sources=new hT,this._sourcesContent=[],this._mappings=[],this.file=r,this.sourceRoot=a,this._ignoreList=new hT});var vT=function(e,t,r,a,n,s,o,i){return TT(!0,e,t,r,a,n,s,o,i)},RT=function(e,t){return function(e,t,r){var a=r.generated,n=r.source,s=r.original,o=r.name,i=r.content;if(!n)return TT(e,t,a.line-1,a.column,null,null,null,null,null);return TT(e,t,a.line-1,a.column,n,s.line-1,s.column,o,i)}(!0,e,t)};function jT(e,t,r){var a=e,n=a._sources;a._sourcesContent[bT(n,t)]=r}function wT(e,t,r){var a=e,n=a._sources,s=a._sourcesContent,o=a._ignoreList,i=bT(n,t);i===s.length&&(s[i]=null),bT(o,i)}function ET(e){var t=e,r=t._mappings,a=t._sources,n=t._sourcesContent,s=t._names,o=t._ignoreList;return function(e){for(var t=e.length,r=t,a=r-1;a>=0&&!(e[a].length>0);r=a,a--);r=0;r=a--){if(t>=e[a][0])break}return r}(g,a);if(!n){if(function(e,t){if(0===t)return!0;var r=e[t-1];return 1===r.length}(g,y))return;return PT(g,y,[a])}var m=bT(u,n),h=i?bT(f,i):-1;if(m===p.length&&(p[m]=null!=d?d:null),!function(e,t,r,a,n,s){if(0===t)return!1;var o=e[t-1];return 1!==o.length&&(r===o[1]&&a===o[2]&&n===o[3]&&s===(5===o.length?o[4]:-1))}(g,y,m,s,o,h))return PT(g,y,i?[a,m,s,o,h]:[a,m,s,o])}function PT(e,t,r){for(var a=e.length;a>t;a--)e[a]=e[a-1];e[t]=r}var AT=function(){function e(e,t){var r;this._map=void 0,this._rawMappings=void 0,this._sourceFileName=void 0,this._lastGenLine=0,this._lastSourceLine=0,this._lastSourceColumn=0,this._inputMap=void 0;var a=this._map=new xT({sourceRoot:e.sourceRoot});if(this._sourceFileName=null==(r=e.sourceFileName)?void 0:r.replace(/\\/g,"/"),this._rawMappings=void 0,e.inputSourceMap){this._inputMap=new pT(e.inputSourceMap);var n=this._inputMap.resolvedSources;if(n.length)for(var s=0;s1?this._indentChar.repeat(t):this._indentChar}else this._str+=t>1?String.fromCharCode(e).repeat(t):String.fromCharCode(e);10!==e?(this._mark(r.line,r.column,r.identifierName,r.identifierNamePos,r.filename),this._position.column+=t):(this._position.line++,this._position.column=0),this._canMarkIdName&&(r.identifierName=void 0,r.identifierNamePos=void 0)},t._append=function(e,t,r){var a=e.length,n=this._position;if(this._last=e.charCodeAt(a-1),++this._appendCount>4096?(this._str,this._buf+=this._str,this._str=e,this._appendCount=0):this._str+=e,r||this._map){var s=t.column,o=t.identifierName,i=t.identifierNamePos,d=t.filename,c=t.line;null==o&&null==i||!this._canMarkIdName||(t.identifierName=void 0,t.identifierNamePos=void 0);var l=e.indexOf("\n"),u=0;for(0!==l&&this._mark(c,s,o,i,d);-1!==l;)n.line++,n.column=0,(u=l+1)=0&&10===this._queue[r].char;r--)t++;return t===e&&10===this._last?t+1:t},t.endsWithCharAndNewline=function(){var e=this._queue,t=this._queueCursor;if(0!==t){if(10!==e[t-1].char)return;return t>1?e[t-2].char:this._last}},t.hasContent=function(){return 0!==this._queueCursor||!!this._last},t.exactSource=function(e,t){if(this._map){this.source("start",e);var r=e.identifierName,a=this._sourcePosition;r&&(this._canMarkIdName=!1,a.identifierName=r),t(),r&&(this._canMarkIdName=!0,a.identifierName=void 0,a.identifierNamePos=void 0),this.source("end",e)}else t()},t.source=function(e,t){this._map&&this._normalizePosition(e,t,0)},t.sourceWithOffset=function(e,t,r){this._map&&this._normalizePosition(e,t,r)},t._normalizePosition=function(e,t,r){var a=t[e],n=this._sourcePosition;a&&(n.line=a.line,n.column=Math.max(a.column+r,0),n.filename=t.filename)},t.getCurrentColumn=function(){for(var e=this._queue,t=this._queueCursor,r=-1,a=0,n=0;n",0],["&&",1],["|",2],["^",3],["&",4],["==",5],["===",5],["!=",5],["!==",5],["<",6],[">",6],["<=",6],[">=",6],["in",6],["instanceof",6],[">>",7],["<<",7],[">>>",7],["+",8],["-",8],["*",9],["/",9],["%",9],["**",10]]);function oP(e,t){return"BinaryExpression"===t||"LogicalExpression"===t?sP.get(e.operator):"TSAsExpression"===t||"TSSatisfiesExpression"===t?sP.get("in"):void 0}function iP(e){return"TSAsExpression"===e||"TSSatisfiesExpression"===e||"TSTypeAssertion"===e}var dP=function(e,t){var r=t.type;return("ClassDeclaration"===r||"ClassExpression"===r)&&t.superClass===e},cP=function(e,t){var r=t.type;return("MemberExpression"===r||"OptionalMemberExpression"===r)&&t.object===e||("CallExpression"===r||"OptionalCallExpression"===r||"NewExpression"===r)&&t.callee===e||"TaggedTemplateExpression"===r&&t.tag===e||"TSNonNullExpression"===r};function lP(e){return Boolean(e&(PP.expressionStatement|PP.arrowBody))}function uP(e,t){var r=t.type;if("BinaryExpression"===e.type&&"**"===e.operator&&"BinaryExpression"===r&&"**"===t.operator)return t.left===e;if(dP(e,t))return!0;if(cP(e,t)||"UnaryExpression"===r||"SpreadElement"===r||"AwaitExpression"===r)return!0;var a=oP(t,r);if(null!=a){var n=oP(e,e.type);if(a===n&&"BinaryExpression"===r&&t.right===e||a>n)return!0}}function pP(e,t){var r=t.type;return"ArrayTypeAnnotation"===r||"NullableTypeAnnotation"===r||"IntersectionTypeAnnotation"===r||"UnionTypeAnnotation"===r}function fP(e,t){return("AssignmentExpression"===t.type||"AssignmentPattern"===t.type)&&t.left===e||("BinaryExpression"===t.type&&("|"===t.operator||"&"===t.operator)&&e===t.left||uP(e,t))}function gP(e,t){var r=t.type;return"TSIntersectionType"===r||"TSUnionType"===r||"TSTypeOperator"===r||"TSOptionalType"===r||"TSArrayType"===r||"TSIndexedAccessType"===r&&t.objectType===e||"TSConditionalType"===r&&(t.checkType===e||t.extendsType===e)}function yP(e,t){var r=t.type;return"BinaryExpression"===r||"LogicalExpression"===r||"UnaryExpression"===r||"SpreadElement"===r||cP(e,t)||"AwaitExpression"===r&&aP(e)||"ConditionalExpression"===r&&e===t.test||dP(e,t)||iP(r)}function mP(e,t){return cP(e,t)||YT(t)&&"**"===t.operator&&t.left===e||dP(e,t)}function hP(e,t){var r=t.type;return!!("UnaryExpression"===r||"SpreadElement"===r||"BinaryExpression"===r||"LogicalExpression"===r||"ConditionalExpression"===r&&t.test===e||"AwaitExpression"===r||iP(r))||mP(e,t)}function bP(e,t){return $T(t)&&t.callee===e||eP(t)&&t.object===e}var xP=Object.freeze({__proto__:null,ArrowFunctionExpression:hP,AssignmentExpression:function(e,t,r){return!(!lP(r)||!tP(e.left))||hP(e,t)},AwaitExpression:yP,Binary:uP,BinaryExpression:function(e,t,r){return"in"===e.operator&&Boolean(r&PP.forInOrInitHeadAccumulate)},ClassExpression:function(e,t,r){return Boolean(r&(PP.expressionStatement|PP.exportDefault))},ConditionalExpression:hP,DoExpression:function(e,t,r){return!e.async&&Boolean(r&PP.expressionStatement)},FunctionExpression:function(e,t,r){return Boolean(r&(PP.expressionStatement|PP.exportDefault))},FunctionTypeAnnotation:function(e,t,r){var a=t.type;return"UnionTypeAnnotation"===a||"IntersectionTypeAnnotation"===a||"ArrayTypeAnnotation"===a||Boolean(r&PP.arrowFlowReturnType)},Identifier:function(e,t,r,a){var n,s=t.type;if(null!=(n=e.extra)&&n.parenthesized&&"AssignmentExpression"===s&&t.left===e){var o=t.right.type;if(("FunctionExpression"===o||"ClassExpression"===o)&&null==t.right.id)return!0}return(!a||a(e)===e.name)&&("let"===e.name?!!((eP(t,{object:e,computed:!0})||rP(t,{object:e,computed:!0,optional:!1}))&&r&(PP.expressionStatement|PP.forInitHead|PP.forInHead))||Boolean(r&PP.forOfHead):"async"===e.name&&QT(t,{left:e,await:!1}))},IntersectionTypeAnnotation:pP,LogicalExpression:function(e,t){var r=t.type;if(iP(r))return!0;if("LogicalExpression"!==r)return!1;switch(e.operator){case"||":return"??"===t.operator||"&&"===t.operator;case"&&":return"??"===t.operator;case"??":return"??"!==t.operator}},NullableTypeAnnotation:function(e,t){return JT(t)},ObjectExpression:function(e,t,r){return lP(r)},OptionalCallExpression:bP,OptionalIndexedAccessType:function(e,t){return ZT(t)&&t.objectType===e},OptionalMemberExpression:bP,SequenceExpression:function(e,t){var r=t.type;return!("SequenceExpression"===r||"ParenthesizedExpression"===r||"MemberExpression"===r&&t.property===e||"OptionalMemberExpression"===r&&t.property===e||"TemplateLiteral"===r)&&("ClassDeclaration"===r||("ForOfStatement"===r?t.right===e:"ExportDefaultDeclaration"===r||!nP(t)))},TSAsExpression:fP,TSConditionalType:function(e,t){var r=t.type;return"TSArrayType"===r||"TSIndexedAccessType"===r&&t.objectType===e||"TSOptionalType"===r||"TSTypeOperator"===r||"TSTypeParameter"===r||(("TSIntersectionType"===r||"TSUnionType"===r)&&t.types[0]===e||"TSConditionalType"===r&&(t.checkType===e||t.extendsType===e))},TSConstructorType:gP,TSFunctionType:gP,TSInferType:function(e,t){var r=t.type;return"TSArrayType"===r||"TSIndexedAccessType"===r&&t.objectType===e||"TSOptionalType"===r||!(!e.typeParameter.constraint||"TSIntersectionType"!==r&&"TSUnionType"!==r||t.types[0]!==e)},TSInstantiationExpression:function(e,t){var r=t.type;return("CallExpression"===r||"OptionalCallExpression"===r||"NewExpression"===r||"TSInstantiationExpression"===r)&&!!t.typeParameters},TSIntersectionType:function(e,t){var r=t.type;return"TSTypeOperator"===r||"TSArrayType"===r||"TSIndexedAccessType"===r&&t.objectType===e||"TSOptionalType"===r},TSSatisfiesExpression:fP,TSTypeAssertion:mP,TSTypeOperator:function(e,t){var r=t.type;return"TSArrayType"===r||"TSIndexedAccessType"===r&&t.objectType===e||"TSOptionalType"===r},TSUnionType:function(e,t){var r=t.type;return"TSIntersectionType"===r||"TSTypeOperator"===r||"TSArrayType"===r||"TSIndexedAccessType"===r&&t.objectType===e||"TSOptionalType"===r},UnaryLike:mP,UnionTypeAnnotation:pP,UpdateExpression:function(e,t){return cP(e,t)||dP(e,t)},YieldExpression:yP}),vP=Pa,RP=Sa,jP=ee,wP=Bt,EP=me,SP=he,TP=Se,PP={normal:0,expressionStatement:1,arrowBody:2,exportDefault:4,arrowFlowReturnType:8,forInitHead:16,forInHead:32,forOfHead:64,forInOrInitHeadAccumulate:128,forInOrInitHeadAccumulatePassThroughMask:128};function AP(e){var t=new Map;function r(e,r){var a=t.get(e);t.set(e,a?function(e,t,n,s){var o;return null!=(o=a(e,t,n,s))?o:r(e,t,n,s)}:r)}for(var a=0,n=Object.keys(e);a0&&a._nodesToTokenIndexes.set(e,t)}),this._tokensCache=null}var t=e.prototype;return t.has=function(e){return this._nodesToTokenIndexes.has(e)},t.getIndexes=function(e){return this._nodesToTokenIndexes.get(e)},t.find=function(e,t){var r=this._nodesToTokenIndexes.get(e);if(r)for(var a=0;a=0;a--){var n=r[a];if(t(this._tokens[n],n))return n}return-1},t.findMatching=function(e,t,r){void 0===r&&(r=0);var a=this._nodesToTokenIndexes.get(e);if(a){var n=0,s=r;if(s>1){var o=this._nodesOccurrencesCountCache.get(e);o&&o.test===t&&o.count0&&this._nodesOccurrencesCountCache.set(e,{test:t,count:s,i:n}),i;r--}}}return null},t.matchesOriginal=function(e,t){return e.end-e.start===t.length&&(null!=e.value?e.value===t:this._source.startsWith(t,e.start))},t.startMatches=function(e,t){var r=this._nodesToTokenIndexes.get(e);if(!r)return!1;var a=this._tokens[r[0]];return a.start===e.start&&this.matchesOriginal(a,t)},t.endMatches=function(e,t){var r=this._nodesToTokenIndexes.get(e);if(!r)return!1;var a=this._tokens[r[r.length-1]];return a.end===e.end&&this.matchesOriginal(a,t)},t._getTokensIndexesOfNode=function(e){if(null==e.start||null==e.end)return[];var t=this._findTokensOfNode(e,0,this._tokens.length-1),r=t.first,a=t.last,n=r,s=BP(e);"ExportNamedDeclaration"!==e.type&&"ExportDefaultDeclaration"!==e.type||!e.declaration||"ClassDeclaration"!==e.declaration.type||s.next();for(var o,d=[],c=i(s);!(o=c()).done;){var l=o.value;if(null!=l&&(null!=l.start&&null!=l.end)){for(var u=this._findTokensOfNode(l,n,a),p=u.first,f=n;f>1;if(ethis._tokens[a].start))return a;t=a+1}}return t},t._findLastTokenOfNode=function(e,t,r){for(;t<=r;){var a=r+t>>1;if(ethis._tokens[a].end))return a;t=a+1}}return r},o(e)}();function BP(e){var t,r,a,n,s,o;return p().w(function(d){for(;;)switch(d.n){case 0:if("TemplateLiteral"!==e.type){d.n=6;break}return d.n=1,e.quasis[0];case 1:t=1;case 2:if(!(t2?mA(p):"\\x"+("00"+p).slice(-2)}),"`"==d&&(i=i.replace(/\$\{/g,"\\${")),t.isScriptContext&&(i=i.replace(/<\/(script|style)/gi,"<\\/$1").replace(/ 9 compatibility check + this._offset = this._offset === undefined ? this._outOffset : this._offset; + this._buffer = this._buffer || this._outBuffer; + + if (opts && opts.maxLength != null) { + this._maxLength = opts.maxLength; + } +} + +function createInflate(opts) { + return new Inflate(opts); +} + +function _close(engine, callback) { + if (callback) { + process.nextTick(callback); + } + + // Caller may invoke .close after a zlib error (which will null _handle). + if (!engine._handle) { + return; + } + + engine._handle.close(); + engine._handle = null; +} + +Inflate.prototype._processChunk = function (chunk, flushFlag, asyncCb) { + if (typeof asyncCb === "function") { + return zlib.Inflate._processChunk.call(this, chunk, flushFlag, asyncCb); + } + + let self = this; + + let availInBefore = chunk && chunk.length; + let availOutBefore = this._chunkSize - this._offset; + let leftToInflate = this._maxLength; + let inOff = 0; + + let buffers = []; + let nread = 0; + + let error; + this.on("error", function (err) { + error = err; + }); + + function handleChunk(availInAfter, availOutAfter) { + if (self._hadError) { + return; + } + + let have = availOutBefore - availOutAfter; + assert(have >= 0, "have should not go down"); + + if (have > 0) { + let out = self._buffer.slice(self._offset, self._offset + have); + self._offset += have; + + if (out.length > leftToInflate) { + out = out.slice(0, leftToInflate); + } + + buffers.push(out); + nread += out.length; + leftToInflate -= out.length; + + if (leftToInflate === 0) { + return false; + } + } + + if (availOutAfter === 0 || self._offset >= self._chunkSize) { + availOutBefore = self._chunkSize; + self._offset = 0; + self._buffer = Buffer.allocUnsafe(self._chunkSize); + } + + if (availOutAfter === 0) { + inOff += availInBefore - availInAfter; + availInBefore = availInAfter; + + return true; + } + + return false; + } + + assert(this._handle, "zlib binding closed"); + let res; + do { + res = this._handle.writeSync( + flushFlag, + chunk, // in + inOff, // in_off + availInBefore, // in_len + this._buffer, // out + this._offset, //out_off + availOutBefore + ); // out_len + // Node 8 --> 9 compatibility check + res = res || this._writeState; + } while (!this._hadError && handleChunk(res[0], res[1])); + + if (this._hadError) { + throw error; + } + + if (nread >= kMaxLength) { + _close(this); + throw new RangeError( + "Cannot create final Buffer. It would be larger than 0x" + + kMaxLength.toString(16) + + " bytes" + ); + } + + let buf = Buffer.concat(buffers, nread); + _close(this); + + return buf; +}; + +util.inherits(Inflate, zlib.Inflate); + +function zlibBufferSync(engine, buffer) { + if (typeof buffer === "string") { + buffer = Buffer.from(buffer); + } + if (!(buffer instanceof Buffer)) { + throw new TypeError("Not a string or buffer"); + } + + let flushFlag = engine._finishFlushFlag; + if (flushFlag == null) { + flushFlag = zlib.Z_FINISH; + } + + return engine._processChunk(buffer, flushFlag); +} + +function inflateSync(buffer, opts) { + return zlibBufferSync(new Inflate(opts), buffer); +} + +module.exports = exports = inflateSync; +exports.Inflate = Inflate; +exports.createInflate = createInflate; +exports.inflateSync = inflateSync; + +}).call(this,require('_process'),require("buffer").Buffer) +},{"_process":47,"assert":23,"buffer":28,"util":67,"zlib":27}],22:[function(require,module,exports){ +"use strict"; + +let SyncReader = (module.exports = function (buffer) { + this._buffer = buffer; + this._reads = []; +}); + +SyncReader.prototype.read = function (length, callback) { + this._reads.push({ + length: Math.abs(length), // if length < 0 then at most this length + allowLess: length < 0, + func: callback, + }); +}; + +SyncReader.prototype.process = function () { + // as long as there is any data and read requests + while (this._reads.length > 0 && this._buffer.length) { + let read = this._reads[0]; + + if ( + this._buffer.length && + (this._buffer.length >= read.length || read.allowLess) + ) { + // ok there is any data so that we can satisfy this request + this._reads.shift(); // == read + + let buf = this._buffer; + + this._buffer = buf.slice(read.length); + + read.func.call(this, buf.slice(0, read.length)); + } else { + break; + } + } + + if (this._reads.length > 0) { + return new Error("There are some read requests waitng on finished stream"); + } + + if (this._buffer.length > 0) { + return new Error("unrecognised content at end of stream"); + } +}; + +},{}],23:[function(require,module,exports){ +(function (global){ +'use strict'; + +// compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js +// original notice: + +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +function compare(a, b) { + if (a === b) { + return 0; + } + + var x = a.length; + var y = b.length; + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i]; + y = b[i]; + break; + } + } + + if (x < y) { + return -1; + } + if (y < x) { + return 1; + } + return 0; +} +function isBuffer(b) { + if (global.Buffer && typeof global.Buffer.isBuffer === 'function') { + return global.Buffer.isBuffer(b); + } + return !!(b != null && b._isBuffer); +} + +// based on node assert, original notice: + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.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 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. + +var util = require('util/'); +var hasOwn = Object.prototype.hasOwnProperty; +var pSlice = Array.prototype.slice; +var functionsHaveNames = (function () { + return function foo() {}.name === 'foo'; +}()); +function pToString (obj) { + return Object.prototype.toString.call(obj); +} +function isView(arrbuf) { + if (isBuffer(arrbuf)) { + return false; + } + if (typeof global.ArrayBuffer !== 'function') { + return false; + } + if (typeof ArrayBuffer.isView === 'function') { + return ArrayBuffer.isView(arrbuf); + } + if (!arrbuf) { + return false; + } + if (arrbuf instanceof DataView) { + return true; + } + if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) { + return true; + } + return false; +} +// 1. The assert module provides functions that throw +// AssertionError's when particular conditions are not met. The +// assert module must conform to the following interface. + +var assert = module.exports = ok; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({ message: message, +// actual: actual, +// expected: expected }) + +var regex = /\s*function\s+([^\(\s]*)\s*/; +// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js +function getName(func) { + if (!util.isFunction(func)) { + return; + } + if (functionsHaveNames) { + return func.name; + } + var str = func.toString(); + var match = str.match(regex); + return match && match[1]; +} +assert.AssertionError = function AssertionError(options) { + this.name = 'AssertionError'; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + if (options.message) { + this.message = options.message; + this.generatedMessage = false; + } else { + this.message = getMessage(this); + this.generatedMessage = true; + } + var stackStartFunction = options.stackStartFunction || fail; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } else { + // non v8 browsers so we can have a stacktrace + var err = new Error(); + if (err.stack) { + var out = err.stack; + + // try to strip useless frames + var fn_name = getName(stackStartFunction); + var idx = out.indexOf('\n' + fn_name); + if (idx >= 0) { + // once we have located the function frame + // we need to strip out everything before it (and its line) + var next_line = out.indexOf('\n', idx + 1); + out = out.substring(next_line + 1); + } + + this.stack = out; + } + } +}; + +// assert.AssertionError instanceof Error +util.inherits(assert.AssertionError, Error); + +function truncate(s, n) { + if (typeof s === 'string') { + return s.length < n ? s : s.slice(0, n); + } else { + return s; + } +} +function inspect(something) { + if (functionsHaveNames || !util.isFunction(something)) { + return util.inspect(something); + } + var rawname = getName(something); + var name = rawname ? ': ' + rawname : ''; + return '[Function' + name + ']'; +} +function getMessage(self) { + return truncate(inspect(self.actual), 128) + ' ' + + self.operator + ' ' + + truncate(inspect(self.expected), 128); +} + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. All of the following functions must throw an AssertionError +// when a corresponding condition is not met, with a message that +// may be undefined if not provided. All assertion methods provide +// both the actual and expected values to the assertion error for +// display purposes. + +function fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, !!guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +function ok(value, message) { + if (!value) fail(value, true, message, '==', assert.ok); +} +assert.ok = ok; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, '==', assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, '!=', assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected, false)) { + fail(actual, expected, message, 'deepEqual', assert.deepEqual); + } +}; + +assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { + if (!_deepEqual(actual, expected, true)) { + fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual); + } +}; + +function _deepEqual(actual, expected, strict, memos) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + } else if (isBuffer(actual) && isBuffer(expected)) { + return compare(actual, expected) === 0; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (util.isDate(actual) && util.isDate(expected)) { + return actual.getTime() === expected.getTime(); + + // 7.3 If the expected value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object with the same source and + // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). + } else if (util.isRegExp(actual) && util.isRegExp(expected)) { + return actual.source === expected.source && + actual.global === expected.global && + actual.multiline === expected.multiline && + actual.lastIndex === expected.lastIndex && + actual.ignoreCase === expected.ignoreCase; + + // 7.4. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if ((actual === null || typeof actual !== 'object') && + (expected === null || typeof expected !== 'object')) { + return strict ? actual === expected : actual == expected; + + // If both values are instances of typed arrays, wrap their underlying + // ArrayBuffers in a Buffer each to increase performance + // This optimization requires the arrays to have the same type as checked by + // Object.prototype.toString (aka pToString). Never perform binary + // comparisons for Float*Arrays, though, since e.g. +0 === -0 but their + // bit patterns are not identical. + } else if (isView(actual) && isView(expected) && + pToString(actual) === pToString(expected) && + !(actual instanceof Float32Array || + actual instanceof Float64Array)) { + return compare(new Uint8Array(actual.buffer), + new Uint8Array(expected.buffer)) === 0; + + // 7.5 For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else if (isBuffer(actual) !== isBuffer(expected)) { + return false; + } else { + memos = memos || {actual: [], expected: []}; + + var actualIndex = memos.actual.indexOf(actual); + if (actualIndex !== -1) { + if (actualIndex === memos.expected.indexOf(expected)) { + return true; + } + } + + memos.actual.push(actual); + memos.expected.push(expected); + + return objEquiv(actual, expected, strict, memos); + } +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv(a, b, strict, actualVisitedObjects) { + if (a === null || a === undefined || b === null || b === undefined) + return false; + // if one is a primitive, the other must be same + if (util.isPrimitive(a) || util.isPrimitive(b)) + return a === b; + if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) + return false; + var aIsArgs = isArguments(a); + var bIsArgs = isArguments(b); + if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) + return false; + if (aIsArgs) { + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b, strict); + } + var ka = objectKeys(a); + var kb = objectKeys(b); + var key, i; + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length !== kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] !== kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects)) + return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected, false)) { + fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); + } +}; + +assert.notDeepStrictEqual = notDeepStrictEqual; +function notDeepStrictEqual(actual, expected, message) { + if (_deepEqual(actual, expected, true)) { + fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual); + } +} + + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, '===', assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as +// determined by !==. assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, '!==', assert.notStrictEqual); + } +}; + +function expectedException(actual, expected) { + if (!actual || !expected) { + return false; + } + + if (Object.prototype.toString.call(expected) == '[object RegExp]') { + return expected.test(actual); + } + + try { + if (actual instanceof expected) { + return true; + } + } catch (e) { + // Ignore. The instanceof check doesn't work for arrow functions. + } + + if (Error.isPrototypeOf(expected)) { + return false; + } + + return expected.call({}, actual) === true; +} + +function _tryBlock(block) { + var error; + try { + block(); + } catch (e) { + error = e; + } + return error; +} + +function _throws(shouldThrow, block, expected, message) { + var actual; + + if (typeof block !== 'function') { + throw new TypeError('"block" argument must be a function'); + } + + if (typeof expected === 'string') { + message = expected; + expected = null; + } + + actual = _tryBlock(block); + + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + + (message ? ' ' + message : '.'); + + if (shouldThrow && !actual) { + fail(actual, expected, 'Missing expected exception' + message); + } + + var userProvidedMessage = typeof message === 'string'; + var isUnwantedException = !shouldThrow && util.isError(actual); + var isUnexpectedException = !shouldThrow && actual && !expected; + + if ((isUnwantedException && + userProvidedMessage && + expectedException(actual, expected)) || + isUnexpectedException) { + fail(actual, expected, 'Got unwanted exception' + message); + } + + if ((shouldThrow && actual && expected && + !expectedException(actual, expected)) || (!shouldThrow && actual)) { + throw actual; + } +} + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws(true, block, error, message); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { + _throws(false, block, error, message); +}; + +assert.ifError = function(err) { if (err) throw err; }; + +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + if (hasOwn.call(obj, key)) keys.push(key); + } + return keys; +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"util/":67}],24:[function(require,module,exports){ +'use strict' + +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray + +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} + +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 + +function placeHoldersCount (b64) { + var len = b64.length + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0 +} + +function byteLength (b64) { + // base64 is 4/3 + up to two characters of the original data + return (b64.length * 3 / 4) - placeHoldersCount(b64) +} + +function toByteArray (b64) { + var i, l, tmp, placeHolders, arr + var len = b64.length + placeHolders = placeHoldersCount(b64) + + arr = new Arr((len * 3 / 4) - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? len - 4 : len + + var L = 0 + + for (i = 0; i < l; i += 4) { + tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] + arr[L++] = (tmp >> 16) & 0xFF + arr[L++] = (tmp >> 8) & 0xFF + arr[L++] = tmp & 0xFF + } + + if (placeHolders === 2) { + tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[L++] = tmp & 0xFF + } else if (placeHolders === 1) { + tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[L++] = (tmp >> 8) & 0xFF + arr[L++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var output = '' + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + output += lookup[tmp >> 2] + output += lookup[(tmp << 4) & 0x3F] + output += '==' + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + (uint8[len - 1]) + output += lookup[tmp >> 10] + output += lookup[(tmp >> 4) & 0x3F] + output += lookup[(tmp << 2) & 0x3F] + output += '=' + } + + parts.push(output) + + return parts.join('') +} + +},{}],25:[function(require,module,exports){ + +},{}],26:[function(require,module,exports){ +(function (process,Buffer){ +'use strict'; +/* eslint camelcase: "off" */ + +var assert = require('assert'); + +var Zstream = require('pako/lib/zlib/zstream'); +var zlib_deflate = require('pako/lib/zlib/deflate.js'); +var zlib_inflate = require('pako/lib/zlib/inflate.js'); +var constants = require('pako/lib/zlib/constants'); + +for (var key in constants) { + exports[key] = constants[key]; +} + +// zlib modes +exports.NONE = 0; +exports.DEFLATE = 1; +exports.INFLATE = 2; +exports.GZIP = 3; +exports.GUNZIP = 4; +exports.DEFLATERAW = 5; +exports.INFLATERAW = 6; +exports.UNZIP = 7; + +var GZIP_HEADER_ID1 = 0x1f; +var GZIP_HEADER_ID2 = 0x8b; + +/** + * Emulate Node's zlib C++ layer for use by the JS layer in index.js + */ +function Zlib(mode) { + if (typeof mode !== 'number' || mode < exports.DEFLATE || mode > exports.UNZIP) { + throw new TypeError('Bad argument'); + } + + this.dictionary = null; + this.err = 0; + this.flush = 0; + this.init_done = false; + this.level = 0; + this.memLevel = 0; + this.mode = mode; + this.strategy = 0; + this.windowBits = 0; + this.write_in_progress = false; + this.pending_close = false; + this.gzip_id_bytes_read = 0; +} + +Zlib.prototype.close = function () { + if (this.write_in_progress) { + this.pending_close = true; + return; + } + + this.pending_close = false; + + assert(this.init_done, 'close before init'); + assert(this.mode <= exports.UNZIP); + + if (this.mode === exports.DEFLATE || this.mode === exports.GZIP || this.mode === exports.DEFLATERAW) { + zlib_deflate.deflateEnd(this.strm); + } else if (this.mode === exports.INFLATE || this.mode === exports.GUNZIP || this.mode === exports.INFLATERAW || this.mode === exports.UNZIP) { + zlib_inflate.inflateEnd(this.strm); + } + + this.mode = exports.NONE; + + this.dictionary = null; +}; + +Zlib.prototype.write = function (flush, input, in_off, in_len, out, out_off, out_len) { + return this._write(true, flush, input, in_off, in_len, out, out_off, out_len); +}; + +Zlib.prototype.writeSync = function (flush, input, in_off, in_len, out, out_off, out_len) { + return this._write(false, flush, input, in_off, in_len, out, out_off, out_len); +}; + +Zlib.prototype._write = function (async, flush, input, in_off, in_len, out, out_off, out_len) { + assert.equal(arguments.length, 8); + + assert(this.init_done, 'write before init'); + assert(this.mode !== exports.NONE, 'already finalized'); + assert.equal(false, this.write_in_progress, 'write already in progress'); + assert.equal(false, this.pending_close, 'close is pending'); + + this.write_in_progress = true; + + assert.equal(false, flush === undefined, 'must provide flush value'); + + this.write_in_progress = true; + + if (flush !== exports.Z_NO_FLUSH && flush !== exports.Z_PARTIAL_FLUSH && flush !== exports.Z_SYNC_FLUSH && flush !== exports.Z_FULL_FLUSH && flush !== exports.Z_FINISH && flush !== exports.Z_BLOCK) { + throw new Error('Invalid flush value'); + } + + if (input == null) { + input = Buffer.alloc(0); + in_len = 0; + in_off = 0; + } + + this.strm.avail_in = in_len; + this.strm.input = input; + this.strm.next_in = in_off; + this.strm.avail_out = out_len; + this.strm.output = out; + this.strm.next_out = out_off; + this.flush = flush; + + if (!async) { + // sync version + this._process(); + + if (this._checkError()) { + return this._afterSync(); + } + return; + } + + // async version + var self = this; + process.nextTick(function () { + self._process(); + self._after(); + }); + + return this; +}; + +Zlib.prototype._afterSync = function () { + var avail_out = this.strm.avail_out; + var avail_in = this.strm.avail_in; + + this.write_in_progress = false; + + return [avail_in, avail_out]; +}; + +Zlib.prototype._process = function () { + var next_expected_header_byte = null; + + // If the avail_out is left at 0, then it means that it ran out + // of room. If there was avail_out left over, then it means + // that all of the input was consumed. + switch (this.mode) { + case exports.DEFLATE: + case exports.GZIP: + case exports.DEFLATERAW: + this.err = zlib_deflate.deflate(this.strm, this.flush); + break; + case exports.UNZIP: + if (this.strm.avail_in > 0) { + next_expected_header_byte = this.strm.next_in; + } + + switch (this.gzip_id_bytes_read) { + case 0: + if (next_expected_header_byte === null) { + break; + } + + if (this.strm.input[next_expected_header_byte] === GZIP_HEADER_ID1) { + this.gzip_id_bytes_read = 1; + next_expected_header_byte++; + + if (this.strm.avail_in === 1) { + // The only available byte was already read. + break; + } + } else { + this.mode = exports.INFLATE; + break; + } + + // fallthrough + case 1: + if (next_expected_header_byte === null) { + break; + } + + if (this.strm.input[next_expected_header_byte] === GZIP_HEADER_ID2) { + this.gzip_id_bytes_read = 2; + this.mode = exports.GUNZIP; + } else { + // There is no actual difference between INFLATE and INFLATERAW + // (after initialization). + this.mode = exports.INFLATE; + } + + break; + default: + throw new Error('invalid number of gzip magic number bytes read'); + } + + // fallthrough + case exports.INFLATE: + case exports.GUNZIP: + case exports.INFLATERAW: + this.err = zlib_inflate.inflate(this.strm, this.flush + + // If data was encoded with dictionary + );if (this.err === exports.Z_NEED_DICT && this.dictionary) { + // Load it + this.err = zlib_inflate.inflateSetDictionary(this.strm, this.dictionary); + if (this.err === exports.Z_OK) { + // And try to decode again + this.err = zlib_inflate.inflate(this.strm, this.flush); + } else if (this.err === exports.Z_DATA_ERROR) { + // Both inflateSetDictionary() and inflate() return Z_DATA_ERROR. + // Make it possible for After() to tell a bad dictionary from bad + // input. + this.err = exports.Z_NEED_DICT; + } + } + while (this.strm.avail_in > 0 && this.mode === exports.GUNZIP && this.err === exports.Z_STREAM_END && this.strm.next_in[0] !== 0x00) { + // Bytes remain in input buffer. Perhaps this is another compressed + // member in the same archive, or just trailing garbage. + // Trailing zero bytes are okay, though, since they are frequently + // used for padding. + + this.reset(); + this.err = zlib_inflate.inflate(this.strm, this.flush); + } + break; + default: + throw new Error('Unknown mode ' + this.mode); + } +}; + +Zlib.prototype._checkError = function () { + // Acceptable error states depend on the type of zlib stream. + switch (this.err) { + case exports.Z_OK: + case exports.Z_BUF_ERROR: + if (this.strm.avail_out !== 0 && this.flush === exports.Z_FINISH) { + this._error('unexpected end of file'); + return false; + } + break; + case exports.Z_STREAM_END: + // normal statuses, not fatal + break; + case exports.Z_NEED_DICT: + if (this.dictionary == null) { + this._error('Missing dictionary'); + } else { + this._error('Bad dictionary'); + } + return false; + default: + // something else. + this._error('Zlib error'); + return false; + } + + return true; +}; + +Zlib.prototype._after = function () { + if (!this._checkError()) { + return; + } + + var avail_out = this.strm.avail_out; + var avail_in = this.strm.avail_in; + + this.write_in_progress = false; + + // call the write() cb + this.callback(avail_in, avail_out); + + if (this.pending_close) { + this.close(); + } +}; + +Zlib.prototype._error = function (message) { + if (this.strm.msg) { + message = this.strm.msg; + } + this.onerror(message, this.err + + // no hope of rescue. + );this.write_in_progress = false; + if (this.pending_close) { + this.close(); + } +}; + +Zlib.prototype.init = function (windowBits, level, memLevel, strategy, dictionary) { + assert(arguments.length === 4 || arguments.length === 5, 'init(windowBits, level, memLevel, strategy, [dictionary])'); + + assert(windowBits >= 8 && windowBits <= 15, 'invalid windowBits'); + assert(level >= -1 && level <= 9, 'invalid compression level'); + + assert(memLevel >= 1 && memLevel <= 9, 'invalid memlevel'); + + assert(strategy === exports.Z_FILTERED || strategy === exports.Z_HUFFMAN_ONLY || strategy === exports.Z_RLE || strategy === exports.Z_FIXED || strategy === exports.Z_DEFAULT_STRATEGY, 'invalid strategy'); + + this._init(level, windowBits, memLevel, strategy, dictionary); + this._setDictionary(); +}; + +Zlib.prototype.params = function () { + throw new Error('deflateParams Not supported'); +}; + +Zlib.prototype.reset = function () { + this._reset(); + this._setDictionary(); +}; + +Zlib.prototype._init = function (level, windowBits, memLevel, strategy, dictionary) { + this.level = level; + this.windowBits = windowBits; + this.memLevel = memLevel; + this.strategy = strategy; + + this.flush = exports.Z_NO_FLUSH; + + this.err = exports.Z_OK; + + if (this.mode === exports.GZIP || this.mode === exports.GUNZIP) { + this.windowBits += 16; + } + + if (this.mode === exports.UNZIP) { + this.windowBits += 32; + } + + if (this.mode === exports.DEFLATERAW || this.mode === exports.INFLATERAW) { + this.windowBits = -1 * this.windowBits; + } + + this.strm = new Zstream(); + + switch (this.mode) { + case exports.DEFLATE: + case exports.GZIP: + case exports.DEFLATERAW: + this.err = zlib_deflate.deflateInit2(this.strm, this.level, exports.Z_DEFLATED, this.windowBits, this.memLevel, this.strategy); + break; + case exports.INFLATE: + case exports.GUNZIP: + case exports.INFLATERAW: + case exports.UNZIP: + this.err = zlib_inflate.inflateInit2(this.strm, this.windowBits); + break; + default: + throw new Error('Unknown mode ' + this.mode); + } + + if (this.err !== exports.Z_OK) { + this._error('Init error'); + } + + this.dictionary = dictionary; + + this.write_in_progress = false; + this.init_done = true; +}; + +Zlib.prototype._setDictionary = function () { + if (this.dictionary == null) { + return; + } + + this.err = exports.Z_OK; + + switch (this.mode) { + case exports.DEFLATE: + case exports.DEFLATERAW: + this.err = zlib_deflate.deflateSetDictionary(this.strm, this.dictionary); + break; + default: + break; + } + + if (this.err !== exports.Z_OK) { + this._error('Failed to set dictionary'); + } +}; + +Zlib.prototype._reset = function () { + this.err = exports.Z_OK; + + switch (this.mode) { + case exports.DEFLATE: + case exports.DEFLATERAW: + case exports.GZIP: + this.err = zlib_deflate.deflateReset(this.strm); + break; + case exports.INFLATE: + case exports.INFLATERAW: + case exports.GUNZIP: + this.err = zlib_inflate.inflateReset(this.strm); + break; + default: + break; + } + + if (this.err !== exports.Z_OK) { + this._error('Failed to reset stream'); + } +}; + +exports.Zlib = Zlib; +}).call(this,require('_process'),require("buffer").Buffer) +},{"_process":47,"assert":23,"buffer":28,"pako/lib/zlib/constants":37,"pako/lib/zlib/deflate.js":39,"pako/lib/zlib/inflate.js":41,"pako/lib/zlib/zstream":45}],27:[function(require,module,exports){ +(function (process){ +'use strict'; + +var Buffer = require('buffer').Buffer; +var Transform = require('stream').Transform; +var binding = require('./binding'); +var util = require('util'); +var assert = require('assert').ok; +var kMaxLength = require('buffer').kMaxLength; +var kRangeErrorMessage = 'Cannot create final Buffer. It would be larger ' + 'than 0x' + kMaxLength.toString(16) + ' bytes'; + +// zlib doesn't provide these, so kludge them in following the same +// const naming scheme zlib uses. +binding.Z_MIN_WINDOWBITS = 8; +binding.Z_MAX_WINDOWBITS = 15; +binding.Z_DEFAULT_WINDOWBITS = 15; + +// fewer than 64 bytes per chunk is stupid. +// technically it could work with as few as 8, but even 64 bytes +// is absurdly low. Usually a MB or more is best. +binding.Z_MIN_CHUNK = 64; +binding.Z_MAX_CHUNK = Infinity; +binding.Z_DEFAULT_CHUNK = 16 * 1024; + +binding.Z_MIN_MEMLEVEL = 1; +binding.Z_MAX_MEMLEVEL = 9; +binding.Z_DEFAULT_MEMLEVEL = 8; + +binding.Z_MIN_LEVEL = -1; +binding.Z_MAX_LEVEL = 9; +binding.Z_DEFAULT_LEVEL = binding.Z_DEFAULT_COMPRESSION; + +// expose all the zlib constants +var bkeys = Object.keys(binding); +for (var bk = 0; bk < bkeys.length; bk++) { + var bkey = bkeys[bk]; + if (bkey.match(/^Z/)) { + Object.defineProperty(exports, bkey, { + enumerable: true, value: binding[bkey], writable: false + }); + } +} + +// translation table for return codes. +var codes = { + Z_OK: binding.Z_OK, + Z_STREAM_END: binding.Z_STREAM_END, + Z_NEED_DICT: binding.Z_NEED_DICT, + Z_ERRNO: binding.Z_ERRNO, + Z_STREAM_ERROR: binding.Z_STREAM_ERROR, + Z_DATA_ERROR: binding.Z_DATA_ERROR, + Z_MEM_ERROR: binding.Z_MEM_ERROR, + Z_BUF_ERROR: binding.Z_BUF_ERROR, + Z_VERSION_ERROR: binding.Z_VERSION_ERROR +}; + +var ckeys = Object.keys(codes); +for (var ck = 0; ck < ckeys.length; ck++) { + var ckey = ckeys[ck]; + codes[codes[ckey]] = ckey; +} + +Object.defineProperty(exports, 'codes', { + enumerable: true, value: Object.freeze(codes), writable: false +}); + +exports.Deflate = Deflate; +exports.Inflate = Inflate; +exports.Gzip = Gzip; +exports.Gunzip = Gunzip; +exports.DeflateRaw = DeflateRaw; +exports.InflateRaw = InflateRaw; +exports.Unzip = Unzip; + +exports.createDeflate = function (o) { + return new Deflate(o); +}; + +exports.createInflate = function (o) { + return new Inflate(o); +}; + +exports.createDeflateRaw = function (o) { + return new DeflateRaw(o); +}; + +exports.createInflateRaw = function (o) { + return new InflateRaw(o); +}; + +exports.createGzip = function (o) { + return new Gzip(o); +}; + +exports.createGunzip = function (o) { + return new Gunzip(o); +}; + +exports.createUnzip = function (o) { + return new Unzip(o); +}; + +// Convenience methods. +// compress/decompress a string or buffer in one step. +exports.deflate = function (buffer, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + return zlibBuffer(new Deflate(opts), buffer, callback); +}; + +exports.deflateSync = function (buffer, opts) { + return zlibBufferSync(new Deflate(opts), buffer); +}; + +exports.gzip = function (buffer, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + return zlibBuffer(new Gzip(opts), buffer, callback); +}; + +exports.gzipSync = function (buffer, opts) { + return zlibBufferSync(new Gzip(opts), buffer); +}; + +exports.deflateRaw = function (buffer, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + return zlibBuffer(new DeflateRaw(opts), buffer, callback); +}; + +exports.deflateRawSync = function (buffer, opts) { + return zlibBufferSync(new DeflateRaw(opts), buffer); +}; + +exports.unzip = function (buffer, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + return zlibBuffer(new Unzip(opts), buffer, callback); +}; + +exports.unzipSync = function (buffer, opts) { + return zlibBufferSync(new Unzip(opts), buffer); +}; + +exports.inflate = function (buffer, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + return zlibBuffer(new Inflate(opts), buffer, callback); +}; + +exports.inflateSync = function (buffer, opts) { + return zlibBufferSync(new Inflate(opts), buffer); +}; + +exports.gunzip = function (buffer, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + return zlibBuffer(new Gunzip(opts), buffer, callback); +}; + +exports.gunzipSync = function (buffer, opts) { + return zlibBufferSync(new Gunzip(opts), buffer); +}; + +exports.inflateRaw = function (buffer, opts, callback) { + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + return zlibBuffer(new InflateRaw(opts), buffer, callback); +}; + +exports.inflateRawSync = function (buffer, opts) { + return zlibBufferSync(new InflateRaw(opts), buffer); +}; + +function zlibBuffer(engine, buffer, callback) { + var buffers = []; + var nread = 0; + + engine.on('error', onError); + engine.on('end', onEnd); + + engine.end(buffer); + flow(); + + function flow() { + var chunk; + while (null !== (chunk = engine.read())) { + buffers.push(chunk); + nread += chunk.length; + } + engine.once('readable', flow); + } + + function onError(err) { + engine.removeListener('end', onEnd); + engine.removeListener('readable', flow); + callback(err); + } + + function onEnd() { + var buf; + var err = null; + + if (nread >= kMaxLength) { + err = new RangeError(kRangeErrorMessage); + } else { + buf = Buffer.concat(buffers, nread); + } + + buffers = []; + engine.close(); + callback(err, buf); + } +} + +function zlibBufferSync(engine, buffer) { + if (typeof buffer === 'string') buffer = Buffer.from(buffer); + + if (!Buffer.isBuffer(buffer)) throw new TypeError('Not a string or buffer'); + + var flushFlag = engine._finishFlushFlag; + + return engine._processChunk(buffer, flushFlag); +} + +// generic zlib +// minimal 2-byte header +function Deflate(opts) { + if (!(this instanceof Deflate)) return new Deflate(opts); + Zlib.call(this, opts, binding.DEFLATE); +} + +function Inflate(opts) { + if (!(this instanceof Inflate)) return new Inflate(opts); + Zlib.call(this, opts, binding.INFLATE); +} + +// gzip - bigger header, same deflate compression +function Gzip(opts) { + if (!(this instanceof Gzip)) return new Gzip(opts); + Zlib.call(this, opts, binding.GZIP); +} + +function Gunzip(opts) { + if (!(this instanceof Gunzip)) return new Gunzip(opts); + Zlib.call(this, opts, binding.GUNZIP); +} + +// raw - no header +function DeflateRaw(opts) { + if (!(this instanceof DeflateRaw)) return new DeflateRaw(opts); + Zlib.call(this, opts, binding.DEFLATERAW); +} + +function InflateRaw(opts) { + if (!(this instanceof InflateRaw)) return new InflateRaw(opts); + Zlib.call(this, opts, binding.INFLATERAW); +} + +// auto-detect header. +function Unzip(opts) { + if (!(this instanceof Unzip)) return new Unzip(opts); + Zlib.call(this, opts, binding.UNZIP); +} + +function isValidFlushFlag(flag) { + return flag === binding.Z_NO_FLUSH || flag === binding.Z_PARTIAL_FLUSH || flag === binding.Z_SYNC_FLUSH || flag === binding.Z_FULL_FLUSH || flag === binding.Z_FINISH || flag === binding.Z_BLOCK; +} + +// the Zlib class they all inherit from +// This thing manages the queue of requests, and returns +// true or false if there is anything in the queue when +// you call the .write() method. + +function Zlib(opts, mode) { + var _this = this; + + this._opts = opts = opts || {}; + this._chunkSize = opts.chunkSize || exports.Z_DEFAULT_CHUNK; + + Transform.call(this, opts); + + if (opts.flush && !isValidFlushFlag(opts.flush)) { + throw new Error('Invalid flush flag: ' + opts.flush); + } + if (opts.finishFlush && !isValidFlushFlag(opts.finishFlush)) { + throw new Error('Invalid flush flag: ' + opts.finishFlush); + } + + this._flushFlag = opts.flush || binding.Z_NO_FLUSH; + this._finishFlushFlag = typeof opts.finishFlush !== 'undefined' ? opts.finishFlush : binding.Z_FINISH; + + if (opts.chunkSize) { + if (opts.chunkSize < exports.Z_MIN_CHUNK || opts.chunkSize > exports.Z_MAX_CHUNK) { + throw new Error('Invalid chunk size: ' + opts.chunkSize); + } + } + + if (opts.windowBits) { + if (opts.windowBits < exports.Z_MIN_WINDOWBITS || opts.windowBits > exports.Z_MAX_WINDOWBITS) { + throw new Error('Invalid windowBits: ' + opts.windowBits); + } + } + + if (opts.level) { + if (opts.level < exports.Z_MIN_LEVEL || opts.level > exports.Z_MAX_LEVEL) { + throw new Error('Invalid compression level: ' + opts.level); + } + } + + if (opts.memLevel) { + if (opts.memLevel < exports.Z_MIN_MEMLEVEL || opts.memLevel > exports.Z_MAX_MEMLEVEL) { + throw new Error('Invalid memLevel: ' + opts.memLevel); + } + } + + if (opts.strategy) { + if (opts.strategy != exports.Z_FILTERED && opts.strategy != exports.Z_HUFFMAN_ONLY && opts.strategy != exports.Z_RLE && opts.strategy != exports.Z_FIXED && opts.strategy != exports.Z_DEFAULT_STRATEGY) { + throw new Error('Invalid strategy: ' + opts.strategy); + } + } + + if (opts.dictionary) { + if (!Buffer.isBuffer(opts.dictionary)) { + throw new Error('Invalid dictionary: it should be a Buffer instance'); + } + } + + this._handle = new binding.Zlib(mode); + + var self = this; + this._hadError = false; + this._handle.onerror = function (message, errno) { + // there is no way to cleanly recover. + // continuing only obscures problems. + _close(self); + self._hadError = true; + + var error = new Error(message); + error.errno = errno; + error.code = exports.codes[errno]; + self.emit('error', error); + }; + + var level = exports.Z_DEFAULT_COMPRESSION; + if (typeof opts.level === 'number') level = opts.level; + + var strategy = exports.Z_DEFAULT_STRATEGY; + if (typeof opts.strategy === 'number') strategy = opts.strategy; + + this._handle.init(opts.windowBits || exports.Z_DEFAULT_WINDOWBITS, level, opts.memLevel || exports.Z_DEFAULT_MEMLEVEL, strategy, opts.dictionary); + + this._buffer = Buffer.allocUnsafe(this._chunkSize); + this._offset = 0; + this._level = level; + this._strategy = strategy; + + this.once('end', this.close); + + Object.defineProperty(this, '_closed', { + get: function () { + return !_this._handle; + }, + configurable: true, + enumerable: true + }); +} + +util.inherits(Zlib, Transform); + +Zlib.prototype.params = function (level, strategy, callback) { + if (level < exports.Z_MIN_LEVEL || level > exports.Z_MAX_LEVEL) { + throw new RangeError('Invalid compression level: ' + level); + } + if (strategy != exports.Z_FILTERED && strategy != exports.Z_HUFFMAN_ONLY && strategy != exports.Z_RLE && strategy != exports.Z_FIXED && strategy != exports.Z_DEFAULT_STRATEGY) { + throw new TypeError('Invalid strategy: ' + strategy); + } + + if (this._level !== level || this._strategy !== strategy) { + var self = this; + this.flush(binding.Z_SYNC_FLUSH, function () { + assert(self._handle, 'zlib binding closed'); + self._handle.params(level, strategy); + if (!self._hadError) { + self._level = level; + self._strategy = strategy; + if (callback) callback(); + } + }); + } else { + process.nextTick(callback); + } +}; + +Zlib.prototype.reset = function () { + assert(this._handle, 'zlib binding closed'); + return this._handle.reset(); +}; + +// This is the _flush function called by the transform class, +// internally, when the last chunk has been written. +Zlib.prototype._flush = function (callback) { + this._transform(Buffer.alloc(0), '', callback); +}; + +Zlib.prototype.flush = function (kind, callback) { + var _this2 = this; + + var ws = this._writableState; + + if (typeof kind === 'function' || kind === undefined && !callback) { + callback = kind; + kind = binding.Z_FULL_FLUSH; + } + + if (ws.ended) { + if (callback) process.nextTick(callback); + } else if (ws.ending) { + if (callback) this.once('end', callback); + } else if (ws.needDrain) { + if (callback) { + this.once('drain', function () { + return _this2.flush(kind, callback); + }); + } + } else { + this._flushFlag = kind; + this.write(Buffer.alloc(0), '', callback); + } +}; + +Zlib.prototype.close = function (callback) { + _close(this, callback); + process.nextTick(emitCloseNT, this); +}; + +function _close(engine, callback) { + if (callback) process.nextTick(callback); + + // Caller may invoke .close after a zlib error (which will null _handle). + if (!engine._handle) return; + + engine._handle.close(); + engine._handle = null; +} + +function emitCloseNT(self) { + self.emit('close'); +} + +Zlib.prototype._transform = function (chunk, encoding, cb) { + var flushFlag; + var ws = this._writableState; + var ending = ws.ending || ws.ended; + var last = ending && (!chunk || ws.length === chunk.length); + + if (chunk !== null && !Buffer.isBuffer(chunk)) return cb(new Error('invalid input')); + + if (!this._handle) return cb(new Error('zlib binding closed')); + + // If it's the last chunk, or a final flush, we use the Z_FINISH flush flag + // (or whatever flag was provided using opts.finishFlush). + // If it's explicitly flushing at some other time, then we use + // Z_FULL_FLUSH. Otherwise, use Z_NO_FLUSH for maximum compression + // goodness. + if (last) flushFlag = this._finishFlushFlag;else { + flushFlag = this._flushFlag; + // once we've flushed the last of the queue, stop flushing and + // go back to the normal behavior. + if (chunk.length >= ws.length) { + this._flushFlag = this._opts.flush || binding.Z_NO_FLUSH; + } + } + + this._processChunk(chunk, flushFlag, cb); +}; + +Zlib.prototype._processChunk = function (chunk, flushFlag, cb) { + var availInBefore = chunk && chunk.length; + var availOutBefore = this._chunkSize - this._offset; + var inOff = 0; + + var self = this; + + var async = typeof cb === 'function'; + + if (!async) { + var buffers = []; + var nread = 0; + + var error; + this.on('error', function (er) { + error = er; + }); + + assert(this._handle, 'zlib binding closed'); + do { + var res = this._handle.writeSync(flushFlag, chunk, // in + inOff, // in_off + availInBefore, // in_len + this._buffer, // out + this._offset, //out_off + availOutBefore); // out_len + } while (!this._hadError && callback(res[0], res[1])); + + if (this._hadError) { + throw error; + } + + if (nread >= kMaxLength) { + _close(this); + throw new RangeError(kRangeErrorMessage); + } + + var buf = Buffer.concat(buffers, nread); + _close(this); + + return buf; + } + + assert(this._handle, 'zlib binding closed'); + var req = this._handle.write(flushFlag, chunk, // in + inOff, // in_off + availInBefore, // in_len + this._buffer, // out + this._offset, //out_off + availOutBefore); // out_len + + req.buffer = chunk; + req.callback = callback; + + function callback(availInAfter, availOutAfter) { + // When the callback is used in an async write, the callback's + // context is the `req` object that was created. The req object + // is === this._handle, and that's why it's important to null + // out the values after they are done being used. `this._handle` + // can stay in memory longer than the callback and buffer are needed. + if (this) { + this.buffer = null; + this.callback = null; + } + + if (self._hadError) return; + + var have = availOutBefore - availOutAfter; + assert(have >= 0, 'have should not go down'); + + if (have > 0) { + var out = self._buffer.slice(self._offset, self._offset + have); + self._offset += have; + // serve some output to the consumer. + if (async) { + self.push(out); + } else { + buffers.push(out); + nread += out.length; + } + } + + // exhausted the output buffer, or used all the input create a new one. + if (availOutAfter === 0 || self._offset >= self._chunkSize) { + availOutBefore = self._chunkSize; + self._offset = 0; + self._buffer = Buffer.allocUnsafe(self._chunkSize); + } + + if (availOutAfter === 0) { + // Not actually done. Need to reprocess. + // Also, update the availInBefore to the availInAfter value, + // so that if we have to hit it a third (fourth, etc.) time, + // it'll have the correct byte counts. + inOff += availInBefore - availInAfter; + availInBefore = availInAfter; + + if (!async) return true; + + var newReq = self._handle.write(flushFlag, chunk, inOff, availInBefore, self._buffer, self._offset, self._chunkSize); + newReq.callback = callback; // this same function + newReq.buffer = chunk; + return; + } + + if (!async) return false; + + // finished with the chunk. + cb(); + } +}; + +util.inherits(Deflate, Zlib); +util.inherits(Inflate, Zlib); +util.inherits(Gzip, Zlib); +util.inherits(Gunzip, Zlib); +util.inherits(DeflateRaw, Zlib); +util.inherits(InflateRaw, Zlib); +util.inherits(Unzip, Zlib); +}).call(this,require('_process')) +},{"./binding":26,"_process":47,"assert":23,"buffer":28,"stream":63,"util":67}],28:[function(require,module,exports){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +var base64 = require('base64-js') +var ieee754 = require('ieee754') + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +var K_MAX_LENGTH = 0x7fffffff +exports.kMaxLength = K_MAX_LENGTH + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Print warning and recommend using `buffer` v4.x which has an Object + * implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. + */ +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() + +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && + typeof console.error === 'function') { + console.error( + 'This browser lacks typed array (Uint8Array) support which is required by ' + + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' + ) +} + +function typedArraySupport () { + // Can typed array instances can be augmented? + try { + var arr = new Uint8Array(1) + arr.__proto__ = { __proto__: Uint8Array.prototype, foo: function () { return 42 } } + return arr.foo() === 42 + } catch (e) { + return false + } +} + +Object.defineProperty(Buffer.prototype, 'parent', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.buffer + } +}) + +Object.defineProperty(Buffer.prototype, 'offset', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.byteOffset + } +}) + +function createBuffer (length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('The value "' + length + '" is invalid for option "size"') + } + // Return an augmented `Uint8Array` instance + var buf = new Uint8Array(length) + buf.__proto__ = Buffer.prototype + return buf +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer (arg, encodingOrOffset, length) { + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new TypeError( + 'The "string" argument must be of type string. Received type number' + ) + } + return allocUnsafe(arg) + } + return from(arg, encodingOrOffset, length) +} + +// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 +if (typeof Symbol !== 'undefined' && Symbol.species != null && + Buffer[Symbol.species] === Buffer) { + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true, + enumerable: false, + writable: false + }) +} + +Buffer.poolSize = 8192 // not used by this implementation + +function from (value, encodingOrOffset, length) { + if (typeof value === 'string') { + return fromString(value, encodingOrOffset) + } + + if (ArrayBuffer.isView(value)) { + return fromArrayLike(value) + } + + if (value == null) { + throw TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) + } + + if (isInstance(value, ArrayBuffer) || + (value && isInstance(value.buffer, ArrayBuffer))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof value === 'number') { + throw new TypeError( + 'The "value" argument must not be of type number. Received type number' + ) + } + + var valueOf = value.valueOf && value.valueOf() + if (valueOf != null && valueOf !== value) { + return Buffer.from(valueOf, encodingOrOffset, length) + } + + var b = fromObject(value) + if (b) return b + + if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && + typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from( + value[Symbol.toPrimitive]('string'), encodingOrOffset, length + ) + } + + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(value, encodingOrOffset, length) +} + +// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 +Buffer.prototype.__proto__ = Uint8Array.prototype +Buffer.__proto__ = Uint8Array + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be of type number') + } else if (size < 0) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } +} + +function alloc (size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' + ? createBuffer(size).fill(fill, encoding) + : createBuffer(size).fill(fill) + } + return createBuffer(size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(size, fill, encoding) +} + +function allocUnsafe (size) { + assertSize(size) + return createBuffer(size < 0 ? 0 : checked(size) | 0) +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(size) +} + +function fromString (string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + + var length = byteLength(string, encoding) | 0 + var buf = createBuffer(length) + + var actual = buf.write(string, encoding) + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + buf = buf.slice(0, actual) + } + + return buf +} + +function fromArrayLike (array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + var buf = createBuffer(length) + for (var i = 0; i < length; i += 1) { + buf[i] = array[i] & 255 + } + return buf +} + +function fromArrayBuffer (array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('"offset" is outside of buffer bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('"length" is outside of buffer bounds') + } + + var buf + if (byteOffset === undefined && length === undefined) { + buf = new Uint8Array(array) + } else if (length === undefined) { + buf = new Uint8Array(array, byteOffset) + } else { + buf = new Uint8Array(array, byteOffset, length) + } + + // Return an augmented `Uint8Array` instance + buf.__proto__ = Buffer.prototype + return buf +} + +function fromObject (obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + var buf = createBuffer(len) + + if (buf.length === 0) { + return buf + } + + obj.copy(buf, 0, 0, len) + return buf + } + + if (obj.length !== undefined) { + if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { + return createBuffer(0) + } + return fromArrayLike(obj) + } + + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data) + } +} + +function checked (length) { + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= K_MAX_LENGTH) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} + +Buffer.isBuffer = function isBuffer (b) { + return b != null && b._isBuffer === true && + b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false +} + +Buffer.compare = function compare (a, b) { + if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) + if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError( + 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' + ) + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!Array.isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (isInstance(buf, Uint8Array)) { + buf = Buffer.from(buf) + } + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos) + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + throw new TypeError( + 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + + 'Received type ' + typeof string + ) + } + + var len = string.length + var mustMatch = (arguments.length > 2 && arguments[2] === true) + if (!mustMatch && len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) { + return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 + } + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + var loweredCase = false + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length + } + + if (end <= 0) { + return '' + } + + // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 +Buffer.prototype._isBuffer = true + +function swap (b, n, m) { + var i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} + +Buffer.prototype.toString = function toString () { + var length = this.length + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.toLocaleString = Buffer.prototype.toString + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() + if (this.length > max) str += ' ... ' + return '' +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (isInstance(target, Uint8Array)) { + target = Buffer.from(target, target.offset, target.byteLength) + } + if (!Buffer.isBuffer(target)) { + throw new TypeError( + 'The "target" argument must be one of type Buffer or Uint8Array. ' + + 'Received type ' + (typeof target) + ) + } + + if (start === undefined) { + start = 0 + } + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 + + if (this === target) return 0 + + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) + + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 + } + byteOffset = +byteOffset // Coerce to Number. + if (numberIsNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') +} + +function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1 + var arrLength = arr.length + var valLength = val.length + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } + } + + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + var i + if (dir) { + var foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + var found = true + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } + } + + return -1 +} + +Buffer.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} + +Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + var strLen = string.length + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (numberIsNaN(parsed)) return i + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset >>> 0 + if (isFinite(length)) { + length = length >>> 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; ++i) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf = this.subarray(start, end) + // Return an augmented `Uint8Array` instance + newBuf.__proto__ = Buffer.prototype + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('Index out of range') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + + if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { + // Use built-in when available, missing from IE11 + this.copyWithin(targetStart, start, end) + } else if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (var i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start] + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, end), + targetStart + ) + } + + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + if (val.length === 1) { + var code = val.charCodeAt(0) + if ((encoding === 'utf8' && code < 128) || + encoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code + } + } + } else if (typeof val === 'number') { + val = val & 255 + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 + + if (!val) val = 0 + + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : Buffer.from(val, encoding) + var len = bytes.length + if (len === 0) { + throw new TypeError('The value "' + val + + '" is invalid for argument "value"') + } + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// HELPER FUNCTIONS +// ================ + +var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node takes equal signs as end of the Base64 encoding + str = str.split('=')[0] + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = str.trim().replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass +// the `instanceof` check but they should be treated as of that type. +// See: https://github.com/feross/buffer/issues/166 +function isInstance (obj, type) { + return obj instanceof type || + (obj != null && obj.constructor != null && obj.constructor.name != null && + obj.constructor.name === type.name) +} +function numberIsNaN (obj) { + // For IE11 support + return obj !== obj // eslint-disable-line no-self-compare +} + +},{"base64-js":24,"ieee754":31}],29:[function(require,module,exports){ +(function (Buffer){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. + +function isArray(arg) { + if (Array.isArray) { + return Array.isArray(arg); + } + return objectToString(arg) === '[object Array]'; +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = Buffer.isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +}).call(this,{"isBuffer":require("../../is-buffer/index.js")}) +},{"../../is-buffer/index.js":33}],30:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var objectCreate = Object.create || objectCreatePolyfill +var objectKeys = Object.keys || objectKeysPolyfill +var bind = Function.prototype.bind || functionBindPolyfill + +function EventEmitter() { + if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) { + this._events = objectCreate(null); + this._eventsCount = 0; + } + + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +var defaultMaxListeners = 10; + +var hasDefineProperty; +try { + var o = {}; + if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 }); + hasDefineProperty = o.x === 0; +} catch (err) { hasDefineProperty = false } +if (hasDefineProperty) { + Object.defineProperty(EventEmitter, 'defaultMaxListeners', { + enumerable: true, + get: function() { + return defaultMaxListeners; + }, + set: function(arg) { + // check whether the input is a positive number (whose value is zero or + // greater and not a NaN). + if (typeof arg !== 'number' || arg < 0 || arg !== arg) + throw new TypeError('"defaultMaxListeners" must be a positive number'); + defaultMaxListeners = arg; + } + }); +} else { + EventEmitter.defaultMaxListeners = defaultMaxListeners; +} + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { + if (typeof n !== 'number' || n < 0 || isNaN(n)) + throw new TypeError('"n" argument must be a positive number'); + this._maxListeners = n; + return this; +}; + +function $getMaxListeners(that) { + if (that._maxListeners === undefined) + return EventEmitter.defaultMaxListeners; + return that._maxListeners; +} + +EventEmitter.prototype.getMaxListeners = function getMaxListeners() { + return $getMaxListeners(this); +}; + +// These standalone emit* functions are used to optimize calling of event +// handlers for fast cases because emit() itself often has a variable number of +// arguments and can be deoptimized because of that. These functions always have +// the same number of arguments and thus do not get deoptimized, so the code +// inside them can execute faster. +function emitNone(handler, isFn, self) { + if (isFn) + handler.call(self); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self); + } +} +function emitOne(handler, isFn, self, arg1) { + if (isFn) + handler.call(self, arg1); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1); + } +} +function emitTwo(handler, isFn, self, arg1, arg2) { + if (isFn) + handler.call(self, arg1, arg2); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1, arg2); + } +} +function emitThree(handler, isFn, self, arg1, arg2, arg3) { + if (isFn) + handler.call(self, arg1, arg2, arg3); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1, arg2, arg3); + } +} + +function emitMany(handler, isFn, self, args) { + if (isFn) + handler.apply(self, args); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].apply(self, args); + } +} + +EventEmitter.prototype.emit = function emit(type) { + var er, handler, len, args, i, events; + var doError = (type === 'error'); + + events = this._events; + if (events) + doError = (doError && events.error == null); + else if (!doError) + return false; + + // If there is no 'error' event listener then throw. + if (doError) { + if (arguments.length > 1) + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Unhandled "error" event. (' + er + ')'); + err.context = er; + throw err; + } + return false; + } + + handler = events[type]; + + if (!handler) + return false; + + var isFn = typeof handler === 'function'; + len = arguments.length; + switch (len) { + // fast cases + case 1: + emitNone(handler, isFn, this); + break; + case 2: + emitOne(handler, isFn, this, arguments[1]); + break; + case 3: + emitTwo(handler, isFn, this, arguments[1], arguments[2]); + break; + case 4: + emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); + break; + // slower + default: + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + emitMany(handler, isFn, this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = target._events; + if (!events) { + events = target._events = objectCreate(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (!existing) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + } else { + // If we've already got an array, just append. + if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + } + + // Check for listener leak + if (!existing.warned) { + m = $getMaxListeners(target); + if (m && m > 0 && existing.length > m) { + existing.warned = true; + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' "' + String(type) + '" listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit.'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + if (typeof console === 'object' && console.warn) { + console.warn('%s: %s', w.name, w.message); + } + } + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + switch (arguments.length) { + case 0: + return this.listener.call(this.target); + case 1: + return this.listener.call(this.target, arguments[0]); + case 2: + return this.listener.call(this.target, arguments[0], arguments[1]); + case 3: + return this.listener.call(this.target, arguments[0], arguments[1], + arguments[2]); + default: + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) + args[i] = arguments[i]; + this.listener.apply(this.target, args); + } + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = bind.call(onceWrapper, state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = this._events; + if (!events) + return this; + + list = events[type]; + if (!list) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else + spliceOne(list, position); + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (!events) + return this; + + // not listening for removeListener, no need to emit + if (!events.removeListener) { + if (arguments.length === 0) { + this._events = objectCreate(null); + this._eventsCount = 0; + } else if (events[type]) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = objectKeys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = objectCreate(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (!events) + return []; + + var evlistener = events[type]; + if (!evlistener) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; +}; + +// About 1.5x faster than the two-arg version of Array#splice(). +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) + list[i] = list[k]; + list.pop(); +} + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + +function objectCreatePolyfill(proto) { + var F = function() {}; + F.prototype = proto; + return new F; +} +function objectKeysPolyfill(obj) { + var keys = []; + for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { + keys.push(k); + } + return k; +} +function functionBindPolyfill(context) { + var fn = this; + return function () { + return fn.apply(context, arguments); + }; +} + +},{}],31:[function(require,module,exports){ +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m + var eLen = nBytes * 8 - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} + +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = nBytes * 8 - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128 +} + +},{}],32:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, 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) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],33:[function(require,module,exports){ +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) +} + +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} + +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} + +},{}],34:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; + +},{}],35:[function(require,module,exports){ +'use strict'; + + +var TYPED_OK = (typeof Uint8Array !== 'undefined') && + (typeof Uint16Array !== 'undefined') && + (typeof Int32Array !== 'undefined'); + +function _has(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} + +exports.assign = function (obj /*from1, from2, from3, ...*/) { + var sources = Array.prototype.slice.call(arguments, 1); + while (sources.length) { + var source = sources.shift(); + if (!source) { continue; } + + if (typeof source !== 'object') { + throw new TypeError(source + 'must be non-object'); + } + + for (var p in source) { + if (_has(source, p)) { + obj[p] = source[p]; + } + } + } + + return obj; +}; + + +// reduce buffer size, avoiding mem copy +exports.shrinkBuf = function (buf, size) { + if (buf.length === size) { return buf; } + if (buf.subarray) { return buf.subarray(0, size); } + buf.length = size; + return buf; +}; + + +var fnTyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + if (src.subarray && dest.subarray) { + dest.set(src.subarray(src_offs, src_offs + len), dest_offs); + return; + } + // Fallback to ordinary array + for (var i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + var i, l, len, pos, chunk, result; + + // calculate data length + len = 0; + for (i = 0, l = chunks.length; i < l; i++) { + len += chunks[i].length; + } + + // join chunks + result = new Uint8Array(len); + pos = 0; + for (i = 0, l = chunks.length; i < l; i++) { + chunk = chunks[i]; + result.set(chunk, pos); + pos += chunk.length; + } + + return result; + } +}; + +var fnUntyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + for (var i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + return [].concat.apply([], chunks); + } +}; + + +// Enable/Disable typed arrays use, for testing +// +exports.setTyped = function (on) { + if (on) { + exports.Buf8 = Uint8Array; + exports.Buf16 = Uint16Array; + exports.Buf32 = Int32Array; + exports.assign(exports, fnTyped); + } else { + exports.Buf8 = Array; + exports.Buf16 = Array; + exports.Buf32 = Array; + exports.assign(exports, fnUntyped); + } +}; + +exports.setTyped(TYPED_OK); + +},{}],36:[function(require,module,exports){ +'use strict'; + +// Note: adler32 takes 12% for level 0 and 2% for level 6. +// It isn't worth it to make additional optimizations as in original. +// Small size is preferable. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function adler32(adler, buf, len, pos) { + var s1 = (adler & 0xffff) |0, + s2 = ((adler >>> 16) & 0xffff) |0, + n = 0; + + while (len !== 0) { + // Set limit ~ twice less than 5552, to keep + // s2 in 31-bits, because we force signed ints. + // in other case %= will fail. + n = len > 2000 ? 2000 : len; + len -= n; + + do { + s1 = (s1 + buf[pos++]) |0; + s2 = (s2 + s1) |0; + } while (--n); + + s1 %= 65521; + s2 %= 65521; + } + + return (s1 | (s2 << 16)) |0; +} + + +module.exports = adler32; + +},{}],37:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +module.exports = { + + /* Allowed flush values; see deflate() and inflate() below for details */ + Z_NO_FLUSH: 0, + Z_PARTIAL_FLUSH: 1, + Z_SYNC_FLUSH: 2, + Z_FULL_FLUSH: 3, + Z_FINISH: 4, + Z_BLOCK: 5, + Z_TREES: 6, + + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + Z_OK: 0, + Z_STREAM_END: 1, + Z_NEED_DICT: 2, + Z_ERRNO: -1, + Z_STREAM_ERROR: -2, + Z_DATA_ERROR: -3, + //Z_MEM_ERROR: -4, + Z_BUF_ERROR: -5, + //Z_VERSION_ERROR: -6, + + /* compression levels */ + Z_NO_COMPRESSION: 0, + Z_BEST_SPEED: 1, + Z_BEST_COMPRESSION: 9, + Z_DEFAULT_COMPRESSION: -1, + + + Z_FILTERED: 1, + Z_HUFFMAN_ONLY: 2, + Z_RLE: 3, + Z_FIXED: 4, + Z_DEFAULT_STRATEGY: 0, + + /* Possible values of the data_type field (though see inflate()) */ + Z_BINARY: 0, + Z_TEXT: 1, + //Z_ASCII: 1, // = Z_TEXT (deprecated) + Z_UNKNOWN: 2, + + /* The deflate compression method */ + Z_DEFLATED: 8 + //Z_NULL: null // Use -1 or null inline, depending on var type +}; + +},{}],38:[function(require,module,exports){ +'use strict'; + +// Note: we can't get significant speed boost here. +// So write code to minimize size - no pregenerated tables +// and array tools dependencies. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for (var n = 0; n < 256; n++) { + c = n; + for (var k = 0; k < 8; k++) { + c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, + end = pos + len; + + crc ^= -1; + + for (var i = pos; i < end; i++) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + + +module.exports = crc32; + +},{}],39:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var utils = require('../utils/common'); +var trees = require('./trees'); +var adler32 = require('./adler32'); +var crc32 = require('./crc32'); +var msg = require('./messages'); + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + + +/* Allowed flush values; see deflate() and inflate() below for details */ +var Z_NO_FLUSH = 0; +var Z_PARTIAL_FLUSH = 1; +//var Z_SYNC_FLUSH = 2; +var Z_FULL_FLUSH = 3; +var Z_FINISH = 4; +var Z_BLOCK = 5; +//var Z_TREES = 6; + + +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ +var Z_OK = 0; +var Z_STREAM_END = 1; +//var Z_NEED_DICT = 2; +//var Z_ERRNO = -1; +var Z_STREAM_ERROR = -2; +var Z_DATA_ERROR = -3; +//var Z_MEM_ERROR = -4; +var Z_BUF_ERROR = -5; +//var Z_VERSION_ERROR = -6; + + +/* compression levels */ +//var Z_NO_COMPRESSION = 0; +//var Z_BEST_SPEED = 1; +//var Z_BEST_COMPRESSION = 9; +var Z_DEFAULT_COMPRESSION = -1; + + +var Z_FILTERED = 1; +var Z_HUFFMAN_ONLY = 2; +var Z_RLE = 3; +var Z_FIXED = 4; +var Z_DEFAULT_STRATEGY = 0; + +/* Possible values of the data_type field (though see inflate()) */ +//var Z_BINARY = 0; +//var Z_TEXT = 1; +//var Z_ASCII = 1; // = Z_TEXT +var Z_UNKNOWN = 2; + + +/* The deflate compression method */ +var Z_DEFLATED = 8; + +/*============================================================================*/ + + +var MAX_MEM_LEVEL = 9; +/* Maximum value for memLevel in deflateInit2 */ +var MAX_WBITS = 15; +/* 32K LZ77 window */ +var DEF_MEM_LEVEL = 8; + + +var LENGTH_CODES = 29; +/* number of length codes, not counting the special END_BLOCK code */ +var LITERALS = 256; +/* number of literal bytes 0..255 */ +var L_CODES = LITERALS + 1 + LENGTH_CODES; +/* number of Literal or Length codes, including the END_BLOCK code */ +var D_CODES = 30; +/* number of distance codes */ +var BL_CODES = 19; +/* number of codes used to transfer the bit lengths */ +var HEAP_SIZE = 2 * L_CODES + 1; +/* maximum heap size */ +var MAX_BITS = 15; +/* All codes must not exceed MAX_BITS bits */ + +var MIN_MATCH = 3; +var MAX_MATCH = 258; +var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); + +var PRESET_DICT = 0x20; + +var INIT_STATE = 42; +var EXTRA_STATE = 69; +var NAME_STATE = 73; +var COMMENT_STATE = 91; +var HCRC_STATE = 103; +var BUSY_STATE = 113; +var FINISH_STATE = 666; + +var BS_NEED_MORE = 1; /* block not completed, need more input or more output */ +var BS_BLOCK_DONE = 2; /* block flush performed */ +var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ +var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ + +var OS_CODE = 0x03; // Unix :) . Don't detect, use this default. + +function err(strm, errorCode) { + strm.msg = msg[errorCode]; + return errorCode; +} + +function rank(f) { + return ((f) << 1) - ((f) > 4 ? 9 : 0); +} + +function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } + + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->output buffer and copying into it. + * (See also read_buf()). + */ +function flush_pending(strm) { + var s = strm.state; + + //_tr_flush_bits(s); + var len = s.pending; + if (len > strm.avail_out) { + len = strm.avail_out; + } + if (len === 0) { return; } + + utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); + strm.next_out += len; + s.pending_out += len; + strm.total_out += len; + strm.avail_out -= len; + s.pending -= len; + if (s.pending === 0) { + s.pending_out = 0; + } +} + + +function flush_block_only(s, last) { + trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); + s.block_start = s.strstart; + flush_pending(s.strm); +} + + +function put_byte(s, b) { + s.pending_buf[s.pending++] = b; +} + + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +function putShortMSB(s, b) { +// put_byte(s, (Byte)(b >> 8)); +// put_byte(s, (Byte)(b & 0xff)); + s.pending_buf[s.pending++] = (b >>> 8) & 0xff; + s.pending_buf[s.pending++] = b & 0xff; +} + + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->input buffer and copying from it. + * (See also flush_pending()). + */ +function read_buf(strm, buf, start, size) { + var len = strm.avail_in; + + if (len > size) { len = size; } + if (len === 0) { return 0; } + + strm.avail_in -= len; + + // zmemcpy(buf, strm->next_in, len); + utils.arraySet(buf, strm.input, strm.next_in, len, start); + if (strm.state.wrap === 1) { + strm.adler = adler32(strm.adler, buf, len, start); + } + + else if (strm.state.wrap === 2) { + strm.adler = crc32(strm.adler, buf, len, start); + } + + strm.next_in += len; + strm.total_in += len; + + return len; +} + + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +function longest_match(s, cur_match) { + var chain_length = s.max_chain_length; /* max hash chain length */ + var scan = s.strstart; /* current string */ + var match; /* matched string */ + var len; /* length of current match */ + var best_len = s.prev_length; /* best match length so far */ + var nice_match = s.nice_match; /* stop if match long enough */ + var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? + s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; + + var _win = s.window; // shortcut + + var wmask = s.w_mask; + var prev = s.prev; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + + var strend = s.strstart + MAX_MATCH; + var scan_end1 = _win[scan + best_len - 1]; + var scan_end = _win[scan + best_len]; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s.prev_length >= s.good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (nice_match > s.lookahead) { nice_match = s.lookahead; } + + // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + // Assert(cur_match < s->strstart, "no future"); + match = cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ + + if (_win[match + best_len] !== scan_end || + _win[match + best_len - 1] !== scan_end1 || + _win[match] !== _win[scan] || + _win[++match] !== _win[scan + 1]) { + continue; + } + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2; + match++; + // Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + /*jshint noempty:false*/ + } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + scan < strend); + + // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (strend - scan); + scan = strend - MAX_MATCH; + + if (len > best_len) { + s.match_start = cur_match; + best_len = len; + if (len >= nice_match) { + break; + } + scan_end1 = _win[scan + best_len - 1]; + scan_end = _win[scan + best_len]; + } + } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + + if (best_len <= s.lookahead) { + return best_len; + } + return s.lookahead; +} + + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +function fill_window(s) { + var _w_size = s.w_size; + var p, n, m, more, str; + + //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = s.window_size - s.lookahead - s.strstart; + + // JS ints have 32 bit, block below not needed + /* Deal with !@#$% 64K limit: */ + //if (sizeof(int) <= 2) { + // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + // more = wsize; + // + // } else if (more == (unsigned)(-1)) { + // /* Very unlikely, but possible on 16 bit machine if + // * strstart == 0 && lookahead == 1 (input done a byte at time) + // */ + // more--; + // } + //} + + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { + + utils.arraySet(s.window, s.window, _w_size, _w_size, 0); + s.match_start -= _w_size; + s.strstart -= _w_size; + /* we now have strstart >= MAX_DIST */ + s.block_start -= _w_size; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + + n = s.hash_size; + p = n; + do { + m = s.head[--p]; + s.head[p] = (m >= _w_size ? m - _w_size : 0); + } while (--n); + + n = _w_size; + p = n; + do { + m = s.prev[--p]; + s.prev[p] = (m >= _w_size ? m - _w_size : 0); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); + + more += _w_size; + } + if (s.strm.avail_in === 0) { + break; + } + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + //Assert(more >= 2, "more < 2"); + n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); + s.lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s.lookahead + s.insert >= MIN_MATCH) { + str = s.strstart - s.insert; + s.ins_h = s.window[str]; + + /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; +//#if MIN_MATCH != 3 +// Call update_hash() MIN_MATCH-3 more times +//#endif + while (s.insert) { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + s.insert--; + if (s.lookahead + s.insert < MIN_MATCH) { + break; + } + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ +// if (s.high_water < s.window_size) { +// var curr = s.strstart + s.lookahead; +// var init = 0; +// +// if (s.high_water < curr) { +// /* Previous high water mark below current data -- zero WIN_INIT +// * bytes or up to end of window, whichever is less. +// */ +// init = s.window_size - curr; +// if (init > WIN_INIT) +// init = WIN_INIT; +// zmemzero(s->window + curr, (unsigned)init); +// s->high_water = curr + init; +// } +// else if (s->high_water < (ulg)curr + WIN_INIT) { +// /* High water mark at or above current data, but below current data +// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up +// * to end of window, whichever is less. +// */ +// init = (ulg)curr + WIN_INIT - s->high_water; +// if (init > s->window_size - s->high_water) +// init = s->window_size - s->high_water; +// zmemzero(s->window + s->high_water, (unsigned)init); +// s->high_water += init; +// } +// } +// +// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, +// "not enough room for search"); +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +function deflate_stored(s, flush) { + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + var max_block_size = 0xffff; + + if (max_block_size > s.pending_buf_size - 5) { + max_block_size = s.pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s.lookahead <= 1) { + + //Assert(s->strstart < s->w_size+MAX_DIST(s) || + // s->block_start >= (long)s->w_size, "slide too late"); +// if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || +// s.block_start >= s.w_size)) { +// throw new Error("slide too late"); +// } + + fill_window(s); + if (s.lookahead === 0 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + + if (s.lookahead === 0) { + break; + } + /* flush the current block */ + } + //Assert(s->block_start >= 0L, "block gone"); +// if (s.block_start < 0) throw new Error("block gone"); + + s.strstart += s.lookahead; + s.lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + var max_start = s.block_start + max_block_size; + + if (s.strstart === 0 || s.strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s.lookahead = s.strstart - max_start; + s.strstart = max_start; + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + + + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + + s.insert = 0; + + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + + if (s.strstart > s.block_start) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_NEED_MORE; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +function deflate_fast(s, flush) { + var hash_head; /* head of the hash chain */ + var bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; /* flush the current block */ + } + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + } + if (s.match_length >= MIN_MATCH) { + // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only + + /*** _tr_tally_dist(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH, bflush); ***/ + bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); + + s.lookahead -= s.match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) { + s.match_length--; /* string at strstart already in table */ + do { + s.strstart++; + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s.match_length !== 0); + s.strstart++; + } else + { + s.strstart += s.match_length; + s.match_length = 0; + s.ins_h = s.window[s.strstart]; + /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; + +//#if MIN_MATCH != 3 +// Call UPDATE_HASH() MIN_MATCH-3 more times +//#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s.window[s.strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1); + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +function deflate_slow(s, flush) { + var hash_head; /* head of hash chain */ + var bflush; /* set if current block must be flushed */ + + var max_insert; + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + */ + s.prev_length = s.match_length; + s.prev_match = s.match_start; + s.match_length = MIN_MATCH - 1; + + if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && + s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + + if (s.match_length <= 5 && + (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s.match_length = MIN_MATCH - 1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { + max_insert = s.strstart + s.lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + //check_match(s, s.strstart-1, s.prev_match, s.prev_length); + + /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, + s.prev_length - MIN_MATCH, bflush);***/ + bflush = trees._tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH); + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s.lookahead -= s.prev_length - 1; + s.prev_length -= 2; + do { + if (++s.strstart <= max_insert) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + } while (--s.prev_length !== 0); + s.match_available = 0; + s.match_length = MIN_MATCH - 1; + s.strstart++; + + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + } else if (s.match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); + + if (bflush) { + /*** FLUSH_BLOCK_ONLY(s, 0) ***/ + flush_block_only(s, false); + /***/ + } + s.strstart++; + s.lookahead--; + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s.match_available = 1; + s.strstart++; + s.lookahead--; + } + } + //Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s.match_available) { + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); + + s.match_available = 0; + } + s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_BLOCK_DONE; +} + + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +function deflate_rle(s, flush) { + var bflush; /* set if current block must be flushed */ + var prev; /* byte at distance one to match */ + var scan, strend; /* scan goes up to strend for length of run */ + + var _win = s.window; + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s.lookahead <= MAX_MATCH) { + fill_window(s); + if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s.match_length = 0; + if (s.lookahead >= MIN_MATCH && s.strstart > 0) { + scan = s.strstart - 1; + prev = _win[scan]; + if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { + strend = s.strstart + MAX_MATCH; + do { + /*jshint noempty:false*/ + } while (prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + scan < strend); + s.match_length = MAX_MATCH - (strend - scan); + if (s.match_length > s.lookahead) { + s.match_length = s.lookahead; + } + } + //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s.match_length >= MIN_MATCH) { + //check_match(s, s.strstart, s.strstart - 1, s.match_length); + + /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ + bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH); + + s.lookahead -= s.match_length; + s.strstart += s.match_length; + s.match_length = 0; + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +function deflate_huff(s, flush) { + var bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s.lookahead === 0) { + fill_window(s); + if (s.lookahead === 0) { + if (flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s.match_length = 0; + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +function Config(good_length, max_lazy, nice_length, max_chain, func) { + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; +} + +var configuration_table; + +configuration_table = [ + /* good lazy nice chain */ + new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ + new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ + new Config(4, 5, 16, 8, deflate_fast), /* 2 */ + new Config(4, 6, 32, 32, deflate_fast), /* 3 */ + + new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ + new Config(8, 16, 32, 32, deflate_slow), /* 5 */ + new Config(8, 16, 128, 128, deflate_slow), /* 6 */ + new Config(8, 32, 128, 256, deflate_slow), /* 7 */ + new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ + new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ +]; + + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +function lm_init(s) { + s.window_size = 2 * s.w_size; + + /*** CLEAR_HASH(s); ***/ + zero(s.head); // Fill with NIL (= 0); + + /* Set the default configuration parameters: + */ + s.max_lazy_match = configuration_table[s.level].max_lazy; + s.good_match = configuration_table[s.level].good_length; + s.nice_match = configuration_table[s.level].nice_length; + s.max_chain_length = configuration_table[s.level].max_chain; + + s.strstart = 0; + s.block_start = 0; + s.lookahead = 0; + s.insert = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + s.ins_h = 0; +} + + +function DeflateState() { + this.strm = null; /* pointer back to this zlib stream */ + this.status = 0; /* as the name implies */ + this.pending_buf = null; /* output still pending */ + this.pending_buf_size = 0; /* size of pending_buf */ + this.pending_out = 0; /* next pending byte to output to the stream */ + this.pending = 0; /* nb of bytes in the pending buffer */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.gzhead = null; /* gzip header information to write */ + this.gzindex = 0; /* where in extra, name, or comment */ + this.method = Z_DEFLATED; /* can only be DEFLATED */ + this.last_flush = -1; /* value of flush param for previous deflate call */ + + this.w_size = 0; /* LZ77 window size (32K by default) */ + this.w_bits = 0; /* log2(w_size) (8..16) */ + this.w_mask = 0; /* w_size - 1 */ + + this.window = null; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. + */ + + this.window_size = 0; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + this.prev = null; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + this.head = null; /* Heads of the hash chains or NIL. */ + + this.ins_h = 0; /* hash index of string to be inserted */ + this.hash_size = 0; /* number of elements in hash table */ + this.hash_bits = 0; /* log2(hash_size) */ + this.hash_mask = 0; /* hash_size-1 */ + + this.hash_shift = 0; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + this.block_start = 0; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + this.match_length = 0; /* length of best match */ + this.prev_match = 0; /* previous match */ + this.match_available = 0; /* set if previous match exists */ + this.strstart = 0; /* start of string to insert */ + this.match_start = 0; /* start of matching string */ + this.lookahead = 0; /* number of valid bytes ahead in window */ + + this.prev_length = 0; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + this.max_chain_length = 0; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + this.max_lazy_match = 0; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ + // That's alias to max_lazy_match, don't use directly + //this.max_insert_length = 0; + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + this.level = 0; /* compression level (1..9) */ + this.strategy = 0; /* favor or force Huffman coding*/ + + this.good_match = 0; + /* Use a faster search when the previous match is longer than this */ + + this.nice_match = 0; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + + /* Didn't use ct_data typedef below to suppress compiler warning */ + + // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + // Use flat array of DOUBLE size, with interleaved fata, + // because JS does not support effective + this.dyn_ltree = new utils.Buf16(HEAP_SIZE * 2); + this.dyn_dtree = new utils.Buf16((2 * D_CODES + 1) * 2); + this.bl_tree = new utils.Buf16((2 * BL_CODES + 1) * 2); + zero(this.dyn_ltree); + zero(this.dyn_dtree); + zero(this.bl_tree); + + this.l_desc = null; /* desc. for literal tree */ + this.d_desc = null; /* desc. for distance tree */ + this.bl_desc = null; /* desc. for bit length tree */ + + //ush bl_count[MAX_BITS+1]; + this.bl_count = new utils.Buf16(MAX_BITS + 1); + /* number of codes at each bit length for an optimal tree */ + + //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + this.heap = new utils.Buf16(2 * L_CODES + 1); /* heap used to build the Huffman trees */ + zero(this.heap); + + this.heap_len = 0; /* number of elements in the heap */ + this.heap_max = 0; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + this.depth = new utils.Buf16(2 * L_CODES + 1); //uch depth[2*L_CODES+1]; + zero(this.depth); + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + this.l_buf = 0; /* buffer index for literals or lengths */ + + this.lit_bufsize = 0; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + this.last_lit = 0; /* running index in l_buf */ + + this.d_buf = 0; + /* Buffer index for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + this.opt_len = 0; /* bit length of current block with optimal trees */ + this.static_len = 0; /* bit length of current block with static trees */ + this.matches = 0; /* number of string matches in current block */ + this.insert = 0; /* bytes at end of window left to insert */ + + + this.bi_buf = 0; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + this.bi_valid = 0; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + // Used for window memory init. We safely ignore it for JS. That makes + // sense only for pointers and memory check tools. + //this.high_water = 0; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ +} + + +function deflateResetKeep(strm) { + var s; + + if (!strm || !strm.state) { + return err(strm, Z_STREAM_ERROR); + } + + strm.total_in = strm.total_out = 0; + strm.data_type = Z_UNKNOWN; + + s = strm.state; + s.pending = 0; + s.pending_out = 0; + + if (s.wrap < 0) { + s.wrap = -s.wrap; + /* was made negative by deflate(..., Z_FINISH); */ + } + s.status = (s.wrap ? INIT_STATE : BUSY_STATE); + strm.adler = (s.wrap === 2) ? + 0 // crc32(0, Z_NULL, 0) + : + 1; // adler32(0, Z_NULL, 0) + s.last_flush = Z_NO_FLUSH; + trees._tr_init(s); + return Z_OK; +} + + +function deflateReset(strm) { + var ret = deflateResetKeep(strm); + if (ret === Z_OK) { + lm_init(strm.state); + } + return ret; +} + + +function deflateSetHeader(strm, head) { + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } + strm.state.gzhead = head; + return Z_OK; +} + + +function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { + if (!strm) { // === Z_NULL + return Z_STREAM_ERROR; + } + var wrap = 1; + + if (level === Z_DEFAULT_COMPRESSION) { + level = 6; + } + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } + + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } + + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return err(strm, Z_STREAM_ERROR); + } + + + if (windowBits === 8) { + windowBits = 9; + } + /* until 256-byte window bug fixed */ + + var s = new DeflateState(); + + strm.state = s; + s.strm = strm; + + s.wrap = wrap; + s.gzhead = null; + s.w_bits = windowBits; + s.w_size = 1 << s.w_bits; + s.w_mask = s.w_size - 1; + + s.hash_bits = memLevel + 7; + s.hash_size = 1 << s.hash_bits; + s.hash_mask = s.hash_size - 1; + s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); + + s.window = new utils.Buf8(s.w_size * 2); + s.head = new utils.Buf16(s.hash_size); + s.prev = new utils.Buf16(s.w_size); + + // Don't need mem init magic for JS. + //s.high_water = 0; /* nothing written to s->window yet */ + + s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + s.pending_buf_size = s.lit_bufsize * 4; + + //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + //s->pending_buf = (uchf *) overlay; + s.pending_buf = new utils.Buf8(s.pending_buf_size); + + // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) + //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s.d_buf = 1 * s.lit_bufsize; + + //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + s.l_buf = (1 + 2) * s.lit_bufsize; + + s.level = level; + s.strategy = strategy; + s.method = method; + + return deflateReset(strm); +} + +function deflateInit(strm, level) { + return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); +} + + +function deflate(strm, flush) { + var old_flush, s; + var beg, val; // for gzip header write only + + if (!strm || !strm.state || + flush > Z_BLOCK || flush < 0) { + return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; + } + + s = strm.state; + + if (!strm.output || + (!strm.input && strm.avail_in !== 0) || + (s.status === FINISH_STATE && flush !== Z_FINISH)) { + return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); + } + + s.strm = strm; /* just in case */ + old_flush = s.last_flush; + s.last_flush = flush; + + /* Write the header */ + if (s.status === INIT_STATE) { + + if (s.wrap === 2) { // GZIP header + strm.adler = 0; //crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (!s.gzhead) { // s->gzhead == Z_NULL + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s.status = BUSY_STATE; + } + else { + put_byte(s, (s.gzhead.text ? 1 : 0) + + (s.gzhead.hcrc ? 2 : 0) + + (!s.gzhead.extra ? 0 : 4) + + (!s.gzhead.name ? 0 : 8) + + (!s.gzhead.comment ? 0 : 16) + ); + put_byte(s, s.gzhead.time & 0xff); + put_byte(s, (s.gzhead.time >> 8) & 0xff); + put_byte(s, (s.gzhead.time >> 16) & 0xff); + put_byte(s, (s.gzhead.time >> 24) & 0xff); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, s.gzhead.os & 0xff); + if (s.gzhead.extra && s.gzhead.extra.length) { + put_byte(s, s.gzhead.extra.length & 0xff); + put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); + } + if (s.gzhead.hcrc) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); + } + s.gzindex = 0; + s.status = EXTRA_STATE; + } + } + else // DEFLATE header + { + var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; + var level_flags = -1; + + if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { + level_flags = 0; + } else if (s.level < 6) { + level_flags = 1; + } else if (s.level === 6) { + level_flags = 2; + } else { + level_flags = 3; + } + header |= (level_flags << 6); + if (s.strstart !== 0) { header |= PRESET_DICT; } + header += 31 - (header % 31); + + s.status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s.strstart !== 0) { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + strm.adler = 1; // adler32(0L, Z_NULL, 0); + } + } + +//#ifdef GZIP + if (s.status === EXTRA_STATE) { + if (s.gzhead.extra/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + + while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + break; + } + } + put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); + s.gzindex++; + } + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (s.gzindex === s.gzhead.extra.length) { + s.gzindex = 0; + s.status = NAME_STATE; + } + } + else { + s.status = NAME_STATE; + } + } + if (s.status === NAME_STATE) { + if (s.gzhead.name/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.name.length) { + val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.gzindex = 0; + s.status = COMMENT_STATE; + } + } + else { + s.status = COMMENT_STATE; + } + } + if (s.status === COMMENT_STATE) { + if (s.gzhead.comment/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.comment.length) { + val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.status = HCRC_STATE; + } + } + else { + s.status = HCRC_STATE; + } + } + if (s.status === HCRC_STATE) { + if (s.gzhead.hcrc) { + if (s.pending + 2 > s.pending_buf_size) { + flush_pending(strm); + } + if (s.pending + 2 <= s.pending_buf_size) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + strm.adler = 0; //crc32(0L, Z_NULL, 0); + s.status = BUSY_STATE; + } + } + else { + s.status = BUSY_STATE; + } + } +//#endif + + /* Flush as much pending output as possible */ + if (s.pending !== 0) { + flush_pending(strm); + if (strm.avail_out === 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s.last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && + flush !== Z_FINISH) { + return err(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s.status === FINISH_STATE && strm.avail_in !== 0) { + return err(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm.avail_in !== 0 || s.lookahead !== 0 || + (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { + var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : + (s.strategy === Z_RLE ? deflate_rle(s, flush) : + configuration_table[s.level].func(s, flush)); + + if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { + s.status = FINISH_STATE; + } + if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { + if (strm.avail_out === 0) { + s.last_flush = -1; + /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate === BS_BLOCK_DONE) { + if (flush === Z_PARTIAL_FLUSH) { + trees._tr_align(s); + } + else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + + trees._tr_stored_block(s, 0, 0, false); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush === Z_FULL_FLUSH) { + /*** CLEAR_HASH(s); ***/ /* forget history */ + zero(s.head); // Fill with NIL (= 0); + + if (s.lookahead === 0) { + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + } + } + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + //Assert(strm->avail_out > 0, "bug2"); + //if (strm.avail_out <= 0) { throw new Error("bug2");} + + if (flush !== Z_FINISH) { return Z_OK; } + if (s.wrap <= 0) { return Z_STREAM_END; } + + /* Write the trailer */ + if (s.wrap === 2) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + put_byte(s, (strm.adler >> 16) & 0xff); + put_byte(s, (strm.adler >> 24) & 0xff); + put_byte(s, strm.total_in & 0xff); + put_byte(s, (strm.total_in >> 8) & 0xff); + put_byte(s, (strm.total_in >> 16) & 0xff); + put_byte(s, (strm.total_in >> 24) & 0xff); + } + else + { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s.wrap > 0) { s.wrap = -s.wrap; } + /* write the trailer only once! */ + return s.pending !== 0 ? Z_OK : Z_STREAM_END; +} + +function deflateEnd(strm) { + var status; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + status = strm.state.status; + if (status !== INIT_STATE && + status !== EXTRA_STATE && + status !== NAME_STATE && + status !== COMMENT_STATE && + status !== HCRC_STATE && + status !== BUSY_STATE && + status !== FINISH_STATE + ) { + return err(strm, Z_STREAM_ERROR); + } + + strm.state = null; + + return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; +} + + +/* ========================================================================= + * Initializes the compression dictionary from the given byte + * sequence without producing any compressed output. + */ +function deflateSetDictionary(strm, dictionary) { + var dictLength = dictionary.length; + + var s; + var str, n; + var wrap; + var avail; + var next; + var input; + var tmpDict; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + s = strm.state; + wrap = s.wrap; + + if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { + return Z_STREAM_ERROR; + } + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap === 1) { + /* adler32(strm->adler, dictionary, dictLength); */ + strm.adler = adler32(strm.adler, dictionary, dictLength, 0); + } + + s.wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s.w_size) { + if (wrap === 0) { /* already empty otherwise */ + /*** CLEAR_HASH(s); ***/ + zero(s.head); // Fill with NIL (= 0); + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + /* use the tail */ + // dictionary = dictionary.slice(dictLength - s.w_size); + tmpDict = new utils.Buf8(s.w_size); + utils.arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); + dictionary = tmpDict; + dictLength = s.w_size; + } + /* insert dictionary into window and hash */ + avail = strm.avail_in; + next = strm.next_in; + input = strm.input; + strm.avail_in = dictLength; + strm.next_in = 0; + strm.input = dictionary; + fill_window(s); + while (s.lookahead >= MIN_MATCH) { + str = s.strstart; + n = s.lookahead - (MIN_MATCH - 1); + do { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + + s.head[s.ins_h] = str; + str++; + } while (--n); + s.strstart = str; + s.lookahead = MIN_MATCH - 1; + fill_window(s); + } + s.strstart += s.lookahead; + s.block_start = s.strstart; + s.insert = s.lookahead; + s.lookahead = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + strm.next_in = next; + strm.input = input; + strm.avail_in = avail; + s.wrap = wrap; + return Z_OK; +} + + +exports.deflateInit = deflateInit; +exports.deflateInit2 = deflateInit2; +exports.deflateReset = deflateReset; +exports.deflateResetKeep = deflateResetKeep; +exports.deflateSetHeader = deflateSetHeader; +exports.deflate = deflate; +exports.deflateEnd = deflateEnd; +exports.deflateSetDictionary = deflateSetDictionary; +exports.deflateInfo = 'pako deflate (from Nodeca project)'; + +/* Not implemented +exports.deflateBound = deflateBound; +exports.deflateCopy = deflateCopy; +exports.deflateParams = deflateParams; +exports.deflatePending = deflatePending; +exports.deflatePrime = deflatePrime; +exports.deflateTune = deflateTune; +*/ + +},{"../utils/common":35,"./adler32":36,"./crc32":38,"./messages":43,"./trees":44}],40:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +// See state defs from inflate.js +var BAD = 30; /* got a data error -- remain here until reset */ +var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state.mode === LEN + strm.avail_in >= 6 + strm.avail_out >= 258 + start >= strm.avail_out + state.bits < 8 + + On return, state.mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm.avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm.avail_out >= 258 for each loop to avoid checking for + output space. + */ +module.exports = function inflate_fast(strm, start) { + var state; + var _in; /* local strm.input */ + var last; /* have enough input while in < last */ + var _out; /* local strm.output */ + var beg; /* inflate()'s initial strm.output */ + var end; /* while out < end, enough space available */ +//#ifdef INFLATE_STRICT + var dmax; /* maximum distance from zlib header */ +//#endif + var wsize; /* window size or zero if not using window */ + var whave; /* valid bytes in the window */ + var wnext; /* window write index */ + // Use `s_window` instead `window`, avoid conflict with instrumentation tools + var s_window; /* allocated sliding window, if wsize != 0 */ + var hold; /* local strm.hold */ + var bits; /* local strm.bits */ + var lcode; /* local strm.lencode */ + var dcode; /* local strm.distcode */ + var lmask; /* mask for first level of length codes */ + var dmask; /* mask for first level of distance codes */ + var here; /* retrieved table entry */ + var op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + var len; /* match length, unused bytes */ + var dist; /* match distance */ + var from; /* where to copy match from */ + var from_source; + + + var input, output; // JS specific, because we have no pointers + + /* copy state to local variables */ + state = strm.state; + //here = state.here; + _in = strm.next_in; + input = strm.input; + last = _in + (strm.avail_in - 5); + _out = strm.next_out; + output = strm.output; + beg = _out - (start - strm.avail_out); + end = _out + (strm.avail_out - 257); +//#ifdef INFLATE_STRICT + dmax = state.dmax; +//#endif + wsize = state.wsize; + whave = state.whave; + wnext = state.wnext; + s_window = state.window; + hold = state.hold; + bits = state.bits; + lcode = state.lencode; + dcode = state.distcode; + lmask = (1 << state.lenbits) - 1; + dmask = (1 << state.distbits) - 1; + + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + + here = lcode[hold & lmask]; + + dolen: + for (;;) { // Goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + if (op === 0) { /* literal */ + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + output[_out++] = here & 0xffff/*here.val*/; + } + else if (op & 16) { /* length base */ + len = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & ((1 << op) - 1); + hold >>>= op; + bits -= op; + } + //Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; + + dodist: + for (;;) { // goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + + if (op & 16) { /* distance base */ + dist = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & ((1 << op) - 1); +//#ifdef INFLATE_STRICT + if (dist > dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; + } +//#endif + hold >>>= op; + bits -= op; + //Tracevv((stderr, "inflate: distance %u\n", dist)); + op = _out - beg; /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; + } + +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// if (len <= op - whave) { +// do { +// output[_out++] = 0; +// } while (--len); +// continue top; +// } +// len -= op - whave; +// do { +// output[_out++] = 0; +// } while (--op > whave); +// if (op === 0) { +// from = _out - dist; +// do { +// output[_out++] = output[from++]; +// } while (--len); +// continue top; +// } +//#endif + } + from = 0; // window index + from_source = s_window; + if (wnext === 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = 0; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } + } + else { + from = _out - dist; /* copy direct from output */ + do { /* minimum length is three */ + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } + } + } + else if ((op & 64) === 0) { /* 2nd level distance code */ + here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dodist; + } + else { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } + else if ((op & 64) === 0) { /* 2nd level length code */ + here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dolen; + } + else if (op & 32) { /* end-of-block */ + //Tracevv((stderr, "inflate: end of block\n")); + state.mode = TYPE; + break top; + } + else { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } while (_in < last && _out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; + + /* update state and return */ + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); + strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); + state.hold = hold; + state.bits = bits; + return; +}; + +},{}],41:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var utils = require('../utils/common'); +var adler32 = require('./adler32'); +var crc32 = require('./crc32'); +var inflate_fast = require('./inffast'); +var inflate_table = require('./inftrees'); + +var CODES = 0; +var LENS = 1; +var DISTS = 2; + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + + +/* Allowed flush values; see deflate() and inflate() below for details */ +//var Z_NO_FLUSH = 0; +//var Z_PARTIAL_FLUSH = 1; +//var Z_SYNC_FLUSH = 2; +//var Z_FULL_FLUSH = 3; +var Z_FINISH = 4; +var Z_BLOCK = 5; +var Z_TREES = 6; + + +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ +var Z_OK = 0; +var Z_STREAM_END = 1; +var Z_NEED_DICT = 2; +//var Z_ERRNO = -1; +var Z_STREAM_ERROR = -2; +var Z_DATA_ERROR = -3; +var Z_MEM_ERROR = -4; +var Z_BUF_ERROR = -5; +//var Z_VERSION_ERROR = -6; + +/* The deflate compression method */ +var Z_DEFLATED = 8; + + +/* STATES ====================================================================*/ +/* ===========================================================================*/ + + +var HEAD = 1; /* i: waiting for magic header */ +var FLAGS = 2; /* i: waiting for method and flags (gzip) */ +var TIME = 3; /* i: waiting for modification time (gzip) */ +var OS = 4; /* i: waiting for extra flags and operating system (gzip) */ +var EXLEN = 5; /* i: waiting for extra length (gzip) */ +var EXTRA = 6; /* i: waiting for extra bytes (gzip) */ +var NAME = 7; /* i: waiting for end of file name (gzip) */ +var COMMENT = 8; /* i: waiting for end of comment (gzip) */ +var HCRC = 9; /* i: waiting for header crc (gzip) */ +var DICTID = 10; /* i: waiting for dictionary check value */ +var DICT = 11; /* waiting for inflateSetDictionary() call */ +var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ +var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ +var STORED = 14; /* i: waiting for stored size (length and complement) */ +var COPY_ = 15; /* i/o: same as COPY below, but only first time in */ +var COPY = 16; /* i/o: waiting for input or output to copy stored block */ +var TABLE = 17; /* i: waiting for dynamic block table lengths */ +var LENLENS = 18; /* i: waiting for code length code lengths */ +var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ +var LEN_ = 20; /* i: same as LEN below, but only first time in */ +var LEN = 21; /* i: waiting for length/lit/eob code */ +var LENEXT = 22; /* i: waiting for length extra bits */ +var DIST = 23; /* i: waiting for distance code */ +var DISTEXT = 24; /* i: waiting for distance extra bits */ +var MATCH = 25; /* o: waiting for output space to copy string */ +var LIT = 26; /* o: waiting for output space to write literal */ +var CHECK = 27; /* i: waiting for 32-bit check value */ +var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ +var DONE = 29; /* finished check, done -- remain here until reset */ +var BAD = 30; /* got a data error -- remain here until reset */ +var MEM = 31; /* got an inflate() memory error -- remain here until reset */ +var SYNC = 32; /* looking for synchronization bytes to restart inflate() */ + +/* ===========================================================================*/ + + + +var ENOUGH_LENS = 852; +var ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +var MAX_WBITS = 15; +/* 32K LZ77 window */ +var DEF_WBITS = MAX_WBITS; + + +function zswap32(q) { + return (((q >>> 24) & 0xff) + + ((q >>> 8) & 0xff00) + + ((q & 0xff00) << 8) + + ((q & 0xff) << 24)); +} + + +function InflateState() { + this.mode = 0; /* current inflate mode */ + this.last = false; /* true if processing last block */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.havedict = false; /* true if dictionary provided */ + this.flags = 0; /* gzip header method and flags (0 if zlib) */ + this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ + this.check = 0; /* protected copy of check value */ + this.total = 0; /* protected copy of output count */ + // TODO: may be {} + this.head = null; /* where to save gzip header information */ + + /* sliding window */ + this.wbits = 0; /* log base 2 of requested window size */ + this.wsize = 0; /* window size or zero if not using window */ + this.whave = 0; /* valid bytes in the window */ + this.wnext = 0; /* window write index */ + this.window = null; /* allocated sliding window, if needed */ + + /* bit accumulator */ + this.hold = 0; /* input bit accumulator */ + this.bits = 0; /* number of bits in "in" */ + + /* for string and stored block copying */ + this.length = 0; /* literal or length of data to copy */ + this.offset = 0; /* distance back to copy string from */ + + /* for table and code decoding */ + this.extra = 0; /* extra bits needed */ + + /* fixed and dynamic code tables */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ + this.lenbits = 0; /* index bits for lencode */ + this.distbits = 0; /* index bits for distcode */ + + /* dynamic table building */ + this.ncode = 0; /* number of code length code lengths */ + this.nlen = 0; /* number of length code lengths */ + this.ndist = 0; /* number of distance code lengths */ + this.have = 0; /* number of code lengths in lens[] */ + this.next = null; /* next available space in codes[] */ + + this.lens = new utils.Buf16(320); /* temporary storage for code lengths */ + this.work = new utils.Buf16(288); /* work area for code table building */ + + /* + because we don't have pointers in js, we use lencode and distcode directly + as buffers so we don't need codes + */ + //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ + this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ + this.distdyn = null; /* dynamic table for distance codes (JS specific) */ + this.sane = 0; /* if false, allow invalid distance too far */ + this.back = 0; /* bits back of last unprocessed length/lit */ + this.was = 0; /* initial length of match */ +} + +function inflateResetKeep(strm) { + var state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ''; /*Z_NULL*/ + if (state.wrap) { /* to support ill-conceived Java test suite */ + strm.adler = state.wrap & 1; + } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.dmax = 32768; + state.head = null/*Z_NULL*/; + state.hold = 0; + state.bits = 0; + //state.lencode = state.distcode = state.next = state.codes; + state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS); + state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS); + + state.sane = 1; + state.back = -1; + //Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +function inflateReset(strm) { + var state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); + +} + +function inflateReset2(strm, windowBits) { + var wrap; + var state; + + /* get the state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; + if (windowBits < 48) { + windowBits &= 15; + } + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } + + /* update state and reset the rest of it */ + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); +} + +function inflateInit2(strm, windowBits) { + var ret; + var state; + + if (!strm) { return Z_STREAM_ERROR; } + //strm.msg = Z_NULL; /* in case we return an error */ + + state = new InflateState(); + + //if (state === Z_NULL) return Z_MEM_ERROR; + //Tracev((stderr, "inflate: allocated\n")); + strm.state = state; + state.window = null/*Z_NULL*/; + ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK) { + strm.state = null/*Z_NULL*/; + } + return ret; +} + +function inflateInit(strm) { + return inflateInit2(strm, DEF_WBITS); +} + + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +var virgin = true; + +var lenfix, distfix; // We have no pointers in JS, so keep tables separate + +function fixedtables(state) { + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + var sym; + + lenfix = new utils.Buf32(512); + distfix = new utils.Buf32(32); + + /* literal/length table */ + sym = 0; + while (sym < 144) { state.lens[sym++] = 8; } + while (sym < 256) { state.lens[sym++] = 9; } + while (sym < 280) { state.lens[sym++] = 7; } + while (sym < 288) { state.lens[sym++] = 8; } + + inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); + + /* distance table */ + sym = 0; + while (sym < 32) { state.lens[sym++] = 5; } + + inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); + + /* do this just once */ + virgin = false; + } + + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; +} + + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +function updatewindow(strm, src, end, copy) { + var dist; + var state = strm.state; + + /* if it hasn't been done already, allocate space for the window */ + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; + + state.window = new utils.Buf8(state.wsize); + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state.wsize) { + utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0); + state.wnext = 0; + state.whave = state.wsize; + } + else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; + } + //zmemcpy(state->window + state->wnext, end - copy, dist); + utils.arraySet(state.window, src, end - copy, dist, state.wnext); + copy -= dist; + if (copy) { + //zmemcpy(state->window, end - copy, copy); + utils.arraySet(state.window, src, end - copy, copy, 0); + state.wnext = copy; + state.whave = state.wsize; + } + else { + state.wnext += dist; + if (state.wnext === state.wsize) { state.wnext = 0; } + if (state.whave < state.wsize) { state.whave += dist; } + } + } + return 0; +} + +function inflate(strm, flush) { + var state; + var input, output; // input/output buffers + var next; /* next input INDEX */ + var put; /* next output INDEX */ + var have, left; /* available input and output */ + var hold; /* bit buffer */ + var bits; /* bits in bit buffer */ + var _in, _out; /* save starting available input and output */ + var copy; /* number of stored or match bytes to copy */ + var from; /* where to copy match bytes from */ + var from_source; + var here = 0; /* current decoding table entry */ + var here_bits, here_op, here_val; // paked "here" denormalized (JS specific) + //var last; /* parent table entry */ + var last_bits, last_op, last_val; // paked "last" denormalized (JS specific) + var len; /* length to copy for repeats, bits to drop */ + var ret; /* return code */ + var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */ + var opts; + + var n; // temporary var for NEED_BITS + + var order = /* permutation of code lengths */ + [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; + + + if (!strm || !strm.state || !strm.output || + (!strm.input && strm.avail_in !== 0)) { + return Z_STREAM_ERROR; + } + + state = strm.state; + if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ + + + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + _in = have; + _out = left; + ret = Z_OK; + + inf_leave: // goto emulation + for (;;) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + //=== NEEDBITS(16); + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ + state.check = 0/*crc32(0L, Z_NULL, 0)*/; + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = FLAGS; + break; + } + state.flags = 0; /* expect zlib header */ + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { + strm.msg = 'incorrect header check'; + state.mode = BAD; + break; + } + if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + len = (hold & 0x0f)/*BITS(4)*/ + 8; + if (state.wbits === 0) { + state.wbits = len; + } + else if (len > state.wbits) { + strm.msg = 'invalid window size'; + state.mode = BAD; + break; + } + state.dmax = 1 << len; + //Tracev((stderr, "inflate: zlib header ok\n")); + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = hold & 0x200 ? DICTID : TYPE; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + break; + case FLAGS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.flags = hold; + if ((state.flags & 0xff) !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + if (state.flags & 0xe000) { + strm.msg = 'unknown header flags set'; + state.mode = BAD; + break; + } + if (state.head) { + state.head.text = ((hold >> 8) & 1); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = TIME; + /* falls through */ + case TIME: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.time = hold; + } + if (state.flags & 0x0200) { + //=== CRC4(state.check, hold) + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + hbuf[2] = (hold >>> 16) & 0xff; + hbuf[3] = (hold >>> 24) & 0xff; + state.check = crc32(state.check, hbuf, 4, 0); + //=== + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = OS; + /* falls through */ + case OS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.xflags = (hold & 0xff); + state.head.os = (hold >> 8); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 0x0400) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + else if (state.head) { + state.head.extra = null/*Z_NULL*/; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 0x0400) { + copy = state.length; + if (copy > have) { copy = have; } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + // Use untyped array for more convenient processing later + state.head.extra = new Array(state.head.extra_len); + } + utils.arraySet( + state.head.extra, + input, + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + copy, + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + //zmemcpy(state.head.extra + len, next, + // len + copy > state.head.extra_max ? + // state.head.extra_max - len : copy); + } + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { break inf_leave; } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 0x0800) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + // TODO: 2 or 1 bytes? + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.name_max*/)) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); + + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 0x1000) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.comm_max*/)) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 0x0200) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.check & 0xffff)) { + strm.msg = 'header crc mismatch'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + if (state.head) { + state.head.hcrc = ((state.flags >> 9) & 1); + state.head.done = true; + } + strm.adler = state.check = 0; + state.mode = TYPE; + break; + case DICTID: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + strm.adler = state.check = zswap32(hold); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + return Z_NEED_DICT; + } + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = TYPE; + /* falls through */ + case TYPE: + if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } + /* falls through */ + case TYPEDO: + if (state.last) { + //--- BYTEBITS() ---// + hold >>>= bits & 7; + bits -= bits & 7; + //---// + state.mode = CHECK; + break; + } + //=== NEEDBITS(3); */ + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.last = (hold & 0x01)/*BITS(1)*/; + //--- DROPBITS(1) ---// + hold >>>= 1; + bits -= 1; + //---// + + switch ((hold & 0x03)/*BITS(2)*/) { + case 0: /* stored block */ + //Tracev((stderr, "inflate: stored block%s\n", + // state.last ? " (last)" : "")); + state.mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + //Tracev((stderr, "inflate: fixed codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = LEN_; /* decode codes */ + if (flush === Z_TREES) { + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break inf_leave; + } + break; + case 2: /* dynamic block */ + //Tracev((stderr, "inflate: dynamic codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = TABLE; + break; + case 3: + strm.msg = 'invalid block type'; + state.mode = BAD; + } + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break; + case STORED: + //--- BYTEBITS() ---// /* go to byte boundary */ + hold >>>= bits & 7; + bits -= bits & 7; + //---// + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { + strm.msg = 'invalid stored block lengths'; + state.mode = BAD; + break; + } + state.length = hold & 0xffff; + //Tracev((stderr, "inflate: stored length %u\n", + // state.length)); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = COPY_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { copy = have; } + if (copy > left) { copy = left; } + if (copy === 0) { break inf_leave; } + //--- zmemcpy(put, next, copy); --- + utils.arraySet(output, input, next, copy, put); + //---// + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + //Tracev((stderr, "inflate: stored end\n")); + state.mode = TYPE; + break; + case TABLE: + //=== NEEDBITS(14); */ + while (bits < 14) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// +//#ifndef PKZIP_BUG_WORKAROUND + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = 'too many length or distance symbols'; + state.mode = BAD; + break; + } +//#endif + //Tracev((stderr, "inflate: table sizes ok\n")); + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + //=== NEEDBITS(3); + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + // We have separate tables & no pointers. 2 commented lines below not needed. + //state.next = state.codes; + //state.lencode = state.next; + // Switch to use dynamic table + state.lencode = state.lendyn; + state.lenbits = 7; + + opts = { bits: state.lenbits }; + ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; + + if (ret) { + strm.msg = 'invalid code lengths set'; + state.mode = BAD; + break; + } + //Tracev((stderr, "inflate: code lengths ok\n")); + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_val < 16) { + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.lens[state.have++] = here_val; + } + else { + if (here_val === 16) { + //=== NEEDBITS(here.bits + 2); + n = here_bits + 2; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + if (state.have === 0) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 0x03);//BITS(2); + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + } + else if (here_val === 17) { + //=== NEEDBITS(here.bits + 3); + n = here_bits + 3; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 3 + (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + else { + //=== NEEDBITS(here.bits + 7); + n = here_bits + 7; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 11 + (hold & 0x7f);//BITS(7); + //--- DROPBITS(7) ---// + hold >>>= 7; + bits -= 7; + //---// + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } + + /* handle error breaks in while */ + if (state.mode === BAD) { break; } + + /* check for end-of-block code (better have one) */ + if (state.lens[256] === 0) { + strm.msg = 'invalid code -- missing end-of-block'; + state.mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state.lenbits = 9; + + opts = { bits: state.lenbits }; + ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.lenbits = opts.bits; + // state.lencode = state.next; + + if (ret) { + strm.msg = 'invalid literal/lengths set'; + state.mode = BAD; + break; + } + + state.distbits = 6; + //state.distcode.copy(state.codes); + // Switch to use dynamic table + state.distcode = state.distdyn; + opts = { bits: state.distbits }; + ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.distbits = opts.bits; + // state.distcode = state.next; + + if (ret) { + strm.msg = 'invalid distances set'; + state.mode = BAD; + break; + } + //Tracev((stderr, 'inflate: codes ok\n')); + state.mode = LEN_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + inflate_fast(strm, _out); + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + if (state.mode === TYPE) { + state.back = -1; + } + break; + } + state.back = 0; + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if (here_bits <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_op && (here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.lencode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + state.mode = LIT; + break; + } + if (here_op & 32) { + //Tracevv((stderr, "inflate: end of block\n")); + state.back = -1; + state.mode = TYPE; + break; + } + if (here_op & 64) { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //Tracevv((stderr, "inflate: length %u\n", state.length)); + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (;;) { + here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if ((here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.distcode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + if (here_op & 64) { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break; + } + state.offset = here_val; + state.extra = (here_op) & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } +//#ifdef INFLATE_STRICT + if (state.offset > state.dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +//#endif + //Tracevv((stderr, "inflate: distance %u\n", state.offset)); + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { break inf_leave; } + copy = _out - left; + if (state.offset > copy) { /* copy from window */ + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// Trace((stderr, "inflate.c too far\n")); +// copy -= state.whave; +// if (copy > state.length) { copy = state.length; } +// if (copy > left) { copy = left; } +// left -= copy; +// state.length -= copy; +// do { +// output[put++] = 0; +// } while (--copy); +// if (state.length === 0) { state.mode = LEN; } +// break; +//#endif + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } + else { + from = state.wnext - copy; + } + if (copy > state.length) { copy = state.length; } + from_source = state.window; + } + else { /* copy from output */ + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { copy = left; } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { state.mode = LEN; } + break; + case LIT: + if (left === 0) { break inf_leave; } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + // Use '|' instead of '+' to make sure that result is signed + hold |= input[next++] << bits; + bits += 8; + } + //===// + _out -= left; + strm.total_out += _out; + state.total += _out; + if (_out) { + strm.adler = state.check = + /*UPDATE(state.check, put - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); + + } + _out = left; + // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too + if ((state.flags ? hold : zswap32(hold)) !== state.check) { + strm.msg = 'incorrect data check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: check matches trailer\n")); + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.total & 0xffffffff)) { + strm.msg = 'incorrect length check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: length matches trailer\n")); + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END; + break inf_leave; + case BAD: + ret = Z_DATA_ERROR; + break inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR; + } + } + + // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + + if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && + (state.mode < CHECK || flush !== Z_FINISH))) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { + state.mode = MEM; + return Z_MEM_ERROR; + } + } + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if (state.wrap && _out) { + strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); + } + strm.data_type = state.bits + (state.last ? 64 : 0) + + (state.mode === TYPE ? 128 : 0) + + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { + ret = Z_BUF_ERROR; + } + return ret; +} + +function inflateEnd(strm) { + + if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { + return Z_STREAM_ERROR; + } + + var state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK; +} + +function inflateGetHeader(strm, head) { + var state; + + /* check state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } + + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK; +} + +function inflateSetDictionary(strm, dictionary) { + var dictLength = dictionary.length; + + var state; + var dictid; + var ret; + + /* check state */ + if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } + state = strm.state; + + if (state.wrap !== 0 && state.mode !== DICT) { + return Z_STREAM_ERROR; + } + + /* check for correct dictionary identifier */ + if (state.mode === DICT) { + dictid = 1; /* adler32(0, null, 0)*/ + /* dictid = adler32(dictid, dictionary, dictLength); */ + dictid = adler32(dictid, dictionary, dictLength, 0); + if (dictid !== state.check) { + return Z_DATA_ERROR; + } + } + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary, dictLength, dictLength); + if (ret) { + state.mode = MEM; + return Z_MEM_ERROR; + } + state.havedict = 1; + // Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +exports.inflateReset = inflateReset; +exports.inflateReset2 = inflateReset2; +exports.inflateResetKeep = inflateResetKeep; +exports.inflateInit = inflateInit; +exports.inflateInit2 = inflateInit2; +exports.inflate = inflate; +exports.inflateEnd = inflateEnd; +exports.inflateGetHeader = inflateGetHeader; +exports.inflateSetDictionary = inflateSetDictionary; +exports.inflateInfo = 'pako inflate (from Nodeca project)'; + +/* Not implemented +exports.inflateCopy = inflateCopy; +exports.inflateGetDictionary = inflateGetDictionary; +exports.inflateMark = inflateMark; +exports.inflatePrime = inflatePrime; +exports.inflateSync = inflateSync; +exports.inflateSyncPoint = inflateSyncPoint; +exports.inflateUndermine = inflateUndermine; +*/ + +},{"../utils/common":35,"./adler32":36,"./crc32":38,"./inffast":40,"./inftrees":42}],42:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var utils = require('../utils/common'); + +var MAXBITS = 15; +var ENOUGH_LENS = 852; +var ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +var CODES = 0; +var LENS = 1; +var DISTS = 2; + +var lbase = [ /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 +]; + +var lext = [ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 +]; + +var dbase = [ /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0 +]; + +var dext = [ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 +]; + +module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) +{ + var bits = opts.bits; + //here = opts.here; /* table entry for duplication */ + + var len = 0; /* a code's length in bits */ + var sym = 0; /* index of code symbols */ + var min = 0, max = 0; /* minimum and maximum code lengths */ + var root = 0; /* number of index bits for root table */ + var curr = 0; /* number of index bits for current table */ + var drop = 0; /* code bits to drop for sub-table */ + var left = 0; /* number of prefix codes available */ + var used = 0; /* code entries in table used */ + var huff = 0; /* Huffman code */ + var incr; /* for incrementing code, index */ + var fill; /* index for replicating entries */ + var low; /* low bits for current root entry */ + var mask; /* mask for low root bits */ + var next; /* next available space in table */ + var base = null; /* base value table to use */ + var base_index = 0; +// var shoextra; /* extra bits table to use */ + var end; /* use base and extra for symbol > end */ + var count = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ + var offs = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ + var extra = null; + var extra_index = 0; + + var here_bits, here_op, here_val; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; + } + + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { break; } + } + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + //table.bits[opts.table_index] = 1; //here.bits = (var char)1; + //table.val[opts.table_index++] = 0; //here.val = (var short)0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + + //table.op[opts.table_index] = 64; + //table.bits[opts.table_index] = 1; + //table.val[opts.table_index++] = 0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { break; } + } + if (root < min) { + root = min; + } + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } /* over-subscribed */ + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; /* incomplete set */ + } + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + // poor man optimization - use if-else instead of switch, + // to avoid deopts in old v8 + if (type === CODES) { + base = extra = work; /* dummy value--not used */ + end = 19; + + } else if (type === LENS) { + base = lbase; + base_index -= 257; + extra = lext; + extra_index -= 257; + end = 256; + + } else { /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here_bits = len - drop; + if (work[sym] < end) { + here_op = 0; + here_val = work[sym]; + } + else if (work[sym] > end) { + here_op = extra[extra_index + work[sym]]; + here_val = base[base_index + work[sym]]; + } + else { + here_op = 32 + 64; /* end of block */ + here_val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << (len - drop); + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; + } while (fill !== 0); + + /* backwards increment the len-bit code huff */ + incr = 1 << (len - 1); + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + + /* go to next symbol, update count, len */ + sym++; + if (--count[len] === 0) { + if (len === max) { break; } + len = lens[lens_index + work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) !== low) { + /* if first time, transition to sub-tables */ + if (drop === 0) { + drop = root; + } + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { break; } + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1 << curr; + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + /* point entry in root table to sub-table */ + low = huff & mask; + /*table.op[low] = curr; + table.bits[low] = root; + table.val[low] = next - opts.table_index;*/ + table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff !== 0) { + //table.op[next + huff] = 64; /* invalid code marker */ + //table.bits[next + huff] = len - drop; + //table.val[next + huff] = 0; + table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; + } + + /* set return parameters */ + //opts.table_index += used; + opts.bits = root; + return 0; +}; + +},{"../utils/common":35}],43:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +module.exports = { + 2: 'need dictionary', /* Z_NEED_DICT 2 */ + 1: 'stream end', /* Z_STREAM_END 1 */ + 0: '', /* Z_OK 0 */ + '-1': 'file error', /* Z_ERRNO (-1) */ + '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ + '-3': 'data error', /* Z_DATA_ERROR (-3) */ + '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ + '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ + '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ +}; + +},{}],44:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var utils = require('../utils/common'); + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + + +//var Z_FILTERED = 1; +//var Z_HUFFMAN_ONLY = 2; +//var Z_RLE = 3; +var Z_FIXED = 4; +//var Z_DEFAULT_STRATEGY = 0; + +/* Possible values of the data_type field (though see inflate()) */ +var Z_BINARY = 0; +var Z_TEXT = 1; +//var Z_ASCII = 1; // = Z_TEXT +var Z_UNKNOWN = 2; + +/*============================================================================*/ + + +function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } + +// From zutil.h + +var STORED_BLOCK = 0; +var STATIC_TREES = 1; +var DYN_TREES = 2; +/* The three kinds of block type */ + +var MIN_MATCH = 3; +var MAX_MATCH = 258; +/* The minimum and maximum match lengths */ + +// From deflate.h +/* =========================================================================== + * Internal compression state. + */ + +var LENGTH_CODES = 29; +/* number of length codes, not counting the special END_BLOCK code */ + +var LITERALS = 256; +/* number of literal bytes 0..255 */ + +var L_CODES = LITERALS + 1 + LENGTH_CODES; +/* number of Literal or Length codes, including the END_BLOCK code */ + +var D_CODES = 30; +/* number of distance codes */ + +var BL_CODES = 19; +/* number of codes used to transfer the bit lengths */ + +var HEAP_SIZE = 2 * L_CODES + 1; +/* maximum heap size */ + +var MAX_BITS = 15; +/* All codes must not exceed MAX_BITS bits */ + +var Buf_size = 16; +/* size of bit buffer in bi_buf */ + + +/* =========================================================================== + * Constants + */ + +var MAX_BL_BITS = 7; +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +var END_BLOCK = 256; +/* end of block literal code */ + +var REP_3_6 = 16; +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +var REPZ_3_10 = 17; +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +var REPZ_11_138 = 18; +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +/* eslint-disable comma-spacing,array-bracket-spacing */ +var extra_lbits = /* extra bits for each length code */ + [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; + +var extra_dbits = /* extra bits for each distance code */ + [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; + +var extra_blbits = /* extra bits for each bit length code */ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; + +var bl_order = + [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; +/* eslint-enable comma-spacing,array-bracket-spacing */ + +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +// We pre-fill arrays with 0 to avoid uninitialized gaps + +var DIST_CODE_LEN = 512; /* see definition of array dist_code below */ + +// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 +var static_ltree = new Array((L_CODES + 2) * 2); +zero(static_ltree); +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +var static_dtree = new Array(D_CODES * 2); +zero(static_dtree); +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +var _dist_code = new Array(DIST_CODE_LEN); +zero(_dist_code); +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +var _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); +zero(_length_code); +/* length code for each normalized match length (0 == MIN_MATCH) */ + +var base_length = new Array(LENGTH_CODES); +zero(base_length); +/* First normalized length for each code (0 = MIN_MATCH) */ + +var base_dist = new Array(D_CODES); +zero(base_dist); +/* First normalized distance for each code (0 = distance of 1) */ + + +function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { + + this.static_tree = static_tree; /* static tree or NULL */ + this.extra_bits = extra_bits; /* extra bits for each code or NULL */ + this.extra_base = extra_base; /* base index for extra_bits */ + this.elems = elems; /* max number of elements in the tree */ + this.max_length = max_length; /* max bit length for the codes */ + + // show if `static_tree` has data or dummy - needed for monomorphic objects + this.has_stree = static_tree && static_tree.length; +} + + +var static_l_desc; +var static_d_desc; +var static_bl_desc; + + +function TreeDesc(dyn_tree, stat_desc) { + this.dyn_tree = dyn_tree; /* the dynamic tree */ + this.max_code = 0; /* largest code with non zero frequency */ + this.stat_desc = stat_desc; /* the corresponding static tree */ +} + + + +function d_code(dist) { + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; +} + + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +function put_short(s, w) { +// put_byte(s, (uch)((w) & 0xff)); +// put_byte(s, (uch)((ush)(w) >> 8)); + s.pending_buf[s.pending++] = (w) & 0xff; + s.pending_buf[s.pending++] = (w >>> 8) & 0xff; +} + + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +function send_bits(s, value, length) { + if (s.bi_valid > (Buf_size - length)) { + s.bi_buf |= (value << s.bi_valid) & 0xffff; + put_short(s, s.bi_buf); + s.bi_buf = value >> (Buf_size - s.bi_valid); + s.bi_valid += length - Buf_size; + } else { + s.bi_buf |= (value << s.bi_valid) & 0xffff; + s.bi_valid += length; + } +} + + +function send_code(s, c, tree) { + send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); +} + + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +function bi_reverse(code, len) { + var res = 0; + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + return res >>> 1; +} + + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +function bi_flush(s) { + if (s.bi_valid === 16) { + put_short(s, s.bi_buf); + s.bi_buf = 0; + s.bi_valid = 0; + + } else if (s.bi_valid >= 8) { + s.pending_buf[s.pending++] = s.bi_buf & 0xff; + s.bi_buf >>= 8; + s.bi_valid -= 8; + } +} + + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +function gen_bitlen(s, desc) +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ +{ + var tree = desc.dyn_tree; + var max_code = desc.max_code; + var stree = desc.stat_desc.static_tree; + var has_stree = desc.stat_desc.has_stree; + var extra = desc.stat_desc.extra_bits; + var base = desc.stat_desc.extra_base; + var max_length = desc.stat_desc.max_length; + var h; /* heap index */ + var n, m; /* iterate over the tree elements */ + var bits; /* bit length */ + var xbits; /* extra bits */ + var f; /* frequency */ + var overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) { + s.bl_count[bits] = 0; + } + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ + + for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n * 2 + 1]/*.Len*/ = bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) { continue; } /* not a leaf node */ + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n - base]; + } + f = tree[n * 2]/*.Freq*/; + s.opt_len += f * (bits + xbits); + if (has_stree) { + s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); + } + } + if (overflow === 0) { return; } + + // Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length - 1; + while (s.bl_count[bits] === 0) { bits--; } + s.bl_count[bits]--; /* move one leaf down the tree */ + s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ + s.bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + while (n !== 0) { + m = s.heap[--h]; + if (m > max_code) { continue; } + if (tree[m * 2 + 1]/*.Len*/ !== bits) { + // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; + tree[m * 2 + 1]/*.Len*/ = bits; + } + n--; + } + } +} + + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +function gen_codes(tree, max_code, bl_count) +// ct_data *tree; /* the tree to decorate */ +// int max_code; /* largest code with non zero frequency */ +// ushf *bl_count; /* number of codes at each bit length */ +{ + var next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ + var code = 0; /* running code value */ + var bits; /* bit index */ + var n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits - 1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES - 1; code++) { + base_length[code] = length; + for (n = 0; n < (1 << extra_lbits[code]); n++) { + _length_code[length++] = code; + } + } + //Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length - 1] = code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1 << extra_dbits[code]); n++) { + _dist_code[dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for (; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { + _dist_code[256 + dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) { + bl_count[bits] = 0; + } + + n = 0; + while (n <= 143) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + while (n <= 255) { + static_ltree[n * 2 + 1]/*.Len*/ = 9; + n++; + bl_count[9]++; + } + while (n <= 279) { + static_ltree[n * 2 + 1]/*.Len*/ = 7; + n++; + bl_count[7]++; + } + while (n <= 287) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes(static_ltree, L_CODES + 1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n * 2 + 1]/*.Len*/ = 5; + static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); + } + + // Now data ready and we can init static trees + static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); + static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); + static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); + + //static_init_done = true; +} + + +/* =========================================================================== + * Initialize a new block. + */ +function init_block(s) { + var n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; } + for (n = 0; n < D_CODES; n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; } + for (n = 0; n < BL_CODES; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; } + + s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; + s.opt_len = s.static_len = 0; + s.last_lit = s.matches = 0; +} + + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +function bi_windup(s) +{ + if (s.bi_valid > 8) { + put_short(s, s.bi_buf); + } else if (s.bi_valid > 0) { + //put_byte(s, (Byte)s->bi_buf); + s.pending_buf[s.pending++] = s.bi_buf; + } + s.bi_buf = 0; + s.bi_valid = 0; +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +function copy_block(s, buf, len, header) +//DeflateState *s; +//charf *buf; /* the input data */ +//unsigned len; /* its length */ +//int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + + if (header) { + put_short(s, len); + put_short(s, ~len); + } +// while (len--) { +// put_byte(s, *buf++); +// } + utils.arraySet(s.pending_buf, s.window, buf, len, s.pending); + s.pending += len; +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +function smaller(tree, n, m, depth) { + var _n2 = n * 2; + var _m2 = m * 2; + return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || + (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m])); +} + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +function pqdownheap(s, tree, k) +// deflate_state *s; +// ct_data *tree; /* the tree to restore */ +// int k; /* node to move down */ +{ + var v = s.heap[k]; + var j = k << 1; /* left son of k */ + while (j <= s.heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s.heap_len && + smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s.heap[j], s.depth)) { break; } + + /* Exchange v with the smallest son */ + s.heap[k] = s.heap[j]; + k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s.heap[k] = v; +} + + +// inlined manually +// var SMALLEST = 1; + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +function compress_block(s, ltree, dtree) +// deflate_state *s; +// const ct_data *ltree; /* literal tree */ +// const ct_data *dtree; /* distance tree */ +{ + var dist; /* distance of matched string */ + var lc; /* match length or unmatched char (if dist == 0) */ + var lx = 0; /* running index in l_buf */ + var code; /* the code to send */ + var extra; /* number of extra bits to send */ + + if (s.last_lit !== 0) { + do { + dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | (s.pending_buf[s.d_buf + lx * 2 + 1]); + lc = s.pending_buf[s.l_buf + lx]; + lx++; + + if (dist === 0) { + send_code(s, lc, ltree); /* send a literal byte */ + //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code + LITERALS + 1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra !== 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + //Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra !== 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + // "pendingBuf overflow"); + + } while (lx < s.last_lit); + } + + send_code(s, END_BLOCK, ltree); +} + + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +function build_tree(s, desc) +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ +{ + var tree = desc.dyn_tree; + var stree = desc.stat_desc.static_tree; + var has_stree = desc.stat_desc.has_stree; + var elems = desc.stat_desc.elems; + var n, m; /* iterate over heap elements */ + var max_code = -1; /* largest code with non zero frequency */ + var node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n * 2]/*.Freq*/ !== 0) { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; + + } else { + tree[n * 2 + 1]/*.Len*/ = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s.heap_len < 2) { + node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0); + tree[node * 2]/*.Freq*/ = 1; + s.depth[node] = 0; + s.opt_len--; + + if (has_stree) { + s.static_len -= stree[node * 2 + 1]/*.Len*/; + } + /* node is 0 or 1 so it does not have extra bits */ + } + desc.max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + //pqremove(s, tree, n); /* n = node of least frequency */ + /*** pqremove ***/ + n = s.heap[1/*SMALLEST*/]; + s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; + pqdownheap(s, tree, 1/*SMALLEST*/); + /***/ + + m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ + + s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ + s.heap[--s.heap_max] = m; + + /* Create a new node father of n and m */ + tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; + s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; + tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; + + /* and insert the new node in the heap */ + s.heap[1/*SMALLEST*/] = node++; + pqdownheap(s, tree, 1/*SMALLEST*/); + + } while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes(tree, max_code, s.bl_count); +} + + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +function scan_tree(s, tree, max_code) +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ +{ + var n; /* iterates over all tree elements */ + var prevlen = -1; /* last emitted length */ + var curlen; /* length of current code */ + + var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + var count = 0; /* repeat count of the current code */ + var max_count = 7; /* max repeat count */ + var min_count = 4; /* min repeat count */ + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + s.bl_tree[curlen * 2]/*.Freq*/ += count; + + } else if (curlen !== 0) { + + if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; } + s.bl_tree[REP_3_6 * 2]/*.Freq*/++; + + } else if (count <= 10) { + s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; + + } else { + s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } +} + + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +function send_tree(s, tree, max_code) +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ +{ + var n; /* iterates over all tree elements */ + var prevlen = -1; /* last emitted length */ + var curlen; /* length of current code */ + + var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + var count = 0; /* repeat count of the current code */ + var max_count = 7; /* max repeat count */ + var min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + do { send_code(s, curlen, s.bl_tree); } while (--count !== 0); + + } else if (curlen !== 0) { + if (curlen !== prevlen) { + send_code(s, curlen, s.bl_tree); + count--; + } + //Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s.bl_tree); + send_bits(s, count - 3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s.bl_tree); + send_bits(s, count - 3, 3); + + } else { + send_code(s, REPZ_11_138, s.bl_tree); + send_bits(s, count - 11, 7); + } + + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } +} + + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +function build_bl_tree(s) { + var max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, s.dyn_ltree, s.l_desc.max_code); + scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, s.bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { + break; + } + } + /* Update opt_len to include the bit length tree and counts */ + s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // s->opt_len, s->static_len)); + + return max_blindex; +} + + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +function send_all_trees(s, lcodes, dcodes, blcodes) +// deflate_state *s; +// int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + var rank; /* index in bl_order */ + + //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + // "too many codes"); + //Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); + } + //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ + //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ + //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +function detect_data_type(s) { + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + var black_mask = 0xf3ffc07f; + var n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>>= 1) { + if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) { + return Z_BINARY; + } + } + + /* Check for textual ("white-listed") bytes. */ + if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || + s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + for (n = 32; n < LITERALS; n++) { + if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + } + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + + +var static_init_done = false; + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +function _tr_init(s) +{ + + if (!static_init_done) { + tr_static_init(); + static_init_done = true; + } + + s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); + s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); + s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); + + s.bi_buf = 0; + s.bi_valid = 0; + + /* Initialize the first block of the first file: */ + init_block(s); +} + + +/* =========================================================================== + * Send a stored block + */ +function _tr_stored_block(s, buf, stored_len, last) +//DeflateState *s; +//charf *buf; /* input block */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ + copy_block(s, buf, stored_len, true); /* with header */ +} + + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ +function _tr_align(s) { + send_bits(s, STATIC_TREES << 1, 3); + send_code(s, END_BLOCK, static_ltree); + bi_flush(s); +} + + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +function _tr_flush_block(s, buf, stored_len, last) +//DeflateState *s; +//charf *buf; /* input block, or NULL if too old */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ +{ + var opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + var max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s.level > 0) { + + /* Check if the file is binary or text */ + if (s.strm.data_type === Z_UNKNOWN) { + s.strm.data_type = detect_data_type(s); + } + + /* Construct the literal and distance trees */ + build_tree(s, s.l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + + build_tree(s, s.d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s.opt_len + 3 + 7) >>> 3; + static_lenb = (s.static_len + 3 + 7) >>> 3; + + // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + // s->last_lit)); + + if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; } + + } else { + // Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + + if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) { + /* 4: two words for the lengths */ + + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + + } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { + + send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); + compress_block(s, static_ltree, static_dtree); + + } else { + send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); + send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); + compress_block(s, s.dyn_ltree, s.dyn_dtree); + } + // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); + } + // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + // s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +function _tr_tally(s, dist, lc) +// deflate_state *s; +// unsigned dist; /* distance of matched string */ +// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + //var out_length, in_length, dcode; + + s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff; + s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; + + s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; + s.last_lit++; + + if (dist === 0) { + /* lc is the unmatched char */ + s.dyn_ltree[lc * 2]/*.Freq*/++; + } else { + s.matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + //Assert((ush)dist < (ush)MAX_DIST(s) && + // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; + s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; + } + +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility + +//#ifdef TRUNCATE_BLOCK +// /* Try to guess if it is profitable to stop the current block here */ +// if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { +// /* Compute an upper bound for the compressed length */ +// out_length = s.last_lit*8; +// in_length = s.strstart - s.block_start; +// +// for (dcode = 0; dcode < D_CODES; dcode++) { +// out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); +// } +// out_length >>>= 3; +// //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", +// // s->last_lit, in_length, out_length, +// // 100L - out_length*100L/in_length)); +// if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { +// return true; +// } +// } +//#endif + + return (s.last_lit === s.lit_bufsize - 1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +exports._tr_init = _tr_init; +exports._tr_stored_block = _tr_stored_block; +exports._tr_flush_block = _tr_flush_block; +exports._tr_tally = _tr_tally; +exports._tr_align = _tr_align; + +},{"../utils/common":35}],45:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function ZStream() { + /* next input byte */ + this.input = null; // JS specific, because we have no pointers + this.next_in = 0; + /* number of bytes available at input */ + this.avail_in = 0; + /* total number of input bytes read so far */ + this.total_in = 0; + /* next output byte should be put there */ + this.output = null; // JS specific, because we have no pointers + this.next_out = 0; + /* remaining free space at output */ + this.avail_out = 0; + /* total number of bytes output so far */ + this.total_out = 0; + /* last error message, NULL if no error */ + this.msg = ''/*Z_NULL*/; + /* not visible by applications */ + this.state = null; + /* best guess about the data type: binary or text */ + this.data_type = 2/*Z_UNKNOWN*/; + /* adler32 value of the uncompressed data */ + this.adler = 0; +} + +module.exports = ZStream; + +},{}],46:[function(require,module,exports){ +(function (process){ +'use strict'; + +if (!process.version || + process.version.indexOf('v0.') === 0 || + process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) { + module.exports = nextTick; +} else { + module.exports = process.nextTick; +} + +function nextTick(fn, arg1, arg2, arg3) { + if (typeof fn !== 'function') { + throw new TypeError('"callback" argument must be a function'); + } + var len = arguments.length; + var args, i; + switch (len) { + case 0: + case 1: + return process.nextTick(fn); + case 2: + return process.nextTick(function afterTickOne() { + fn.call(null, arg1); + }); + case 3: + return process.nextTick(function afterTickTwo() { + fn.call(null, arg1, arg2); + }); + case 4: + return process.nextTick(function afterTickThree() { + fn.call(null, arg1, arg2, arg3); + }); + default: + args = new Array(len - 1); + i = 0; + while (i < args.length) { + args[i++] = arguments[i]; + } + return process.nextTick(function afterTick() { + fn.apply(null, args); + }); + } +} + +}).call(this,require('_process')) +},{"_process":47}],47:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],48:[function(require,module,exports){ +module.exports = require('./lib/_stream_duplex.js'); + +},{"./lib/_stream_duplex.js":49}],49:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +'use strict'; + +/**/ + +var processNextTick = require('process-nextick-args'); +/**/ + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +module.exports = Duplex; + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +var keys = objectKeys(Writable.prototype); +for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; +} + +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) this.readable = false; + + if (options && options.writable === false) this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; + + this.once('end', onend); +} + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + processNextTick(onEndNT, this); +} + +function onEndNT(self) { + self.end(); +} + +Object.defineProperty(Duplex.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); + +Duplex.prototype._destroy = function (err, cb) { + this.push(null); + this.end(); + + processNextTick(cb, err); +}; + +function forEach(xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} +},{"./_stream_readable":51,"./_stream_writable":53,"core-util-is":29,"inherits":32,"process-nextick-args":46}],50:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +'use strict'; + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; +},{"./_stream_transform":52,"core-util-is":29,"inherits":32}],51:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var processNextTick = require('process-nextick-args'); +/**/ + +module.exports = Readable; + +/**/ +var isArray = require('isarray'); +/**/ + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = require('events').EventEmitter; + +var EElistenerCount = function (emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +// TODO(bmeurer): Change this back to const once hole checks are +// properly optimized away early in Ignition+TurboFan. +/**/ +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} +/**/ + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +/**/ +var debugUtil = require('util'); +var debug = void 0; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function () {}; +} +/**/ + +var BufferList = require('./internal/streams/BufferList'); +var destroyImpl = require('./internal/streams/destroy'); +var StringDecoder; + +util.inherits(Readable, Stream); + +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; + +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') { + return emitter.prependListener(event, fn); + } else { + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; + } +} + +function ReadableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + if (!(this instanceof Readable)) return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + if (options) { + if (typeof options.read === 'function') this._read = options.read; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + + Stream.call(this); +} + +Object.defineProperty(Readable.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); + +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + this.push(null); + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; + +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (addToFront) { + if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true); + } else if (state.ended) { + stream.emit('error', new Error('stream.push() after EOF')); + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + } + } + + return needMoreData(state); +} + +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} + +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); +} + +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 8MB +var MAX_HWM = 0x800000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } else { + state.length -= n; + } + + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + + if (ret !== null) this.emit('data', ret); + + return ret; +}; + +function onEofChunk(stream, state) { + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + emitReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) processNextTick(emitReadable_, stream);else emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + processNextTick(maybeReadMore_, stream, state); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break;else len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + this.emit('error', new Error('_read() is not implemented')); +}; + +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) processNextTick(endFn);else src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + + // If the user pushes more data while we're writing to dest then we'll end up + // in ondata again. However, we only want to increase awaitDrain once because + // dest will only emit one 'drain' event for the multiple writes. + // => Introduce a guard on increasing awaitDrain. + var increasedAwaitDrain = false; + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + increasedAwaitDrain = false; + var ret = dest.write(chunk); + if (false === ret && !increasedAwaitDrain) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', src._readableState.awaitDrain); + src._readableState.awaitDrain++; + increasedAwaitDrain = true; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function () { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { hasUnpiped: false }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + + for (var i = 0; i < len; i++) { + dests[i].emit('unpipe', this, unpipeInfo); + }return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + + dest.emit('unpipe', this, unpipeInfo); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data') { + // Start flowing on next tick if stream isn't explicitly paused + if (this._readableState.flowing !== false) this.resume(); + } else if (ev === 'readable') { + var state = this._readableState; + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.emittedReadable = false; + if (!state.reading) { + processNextTick(nReadingNextTick, this); + } else if (state.length) { + emitReadable(this); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + state.flowing = true; + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + processNextTick(resume_, stream, state); + } +} + +function resume_(stream, state) { + if (!state.reading) { + debug('resume read 0'); + stream.read(0); + } + + state.resumeScheduled = false; + state.awaitDrain = 0; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} + +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null) {} +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var state = this._readableState; + var paused = false; + + var self = this; + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) self.push(chunk); + } + + self.push(null); + }); + + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + + var ret = self.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function (method) { + return function () { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], self.emit.bind(self, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + self._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return self; +}; + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = fromListPartial(n, state.buffer, state.decoder); + } + + return ret; +} + +// Extracts only enough buffered data to satisfy the amount requested. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromListPartial(n, list, hasStrings) { + var ret; + if (n < list.head.data.length) { + // slice is the same for buffers and strings + ret = list.head.data.slice(0, n); + list.head.data = list.head.data.slice(n); + } else if (n === list.head.data.length) { + // first chunk is a perfect match + ret = list.shift(); + } else { + // result spans more than one buffer + ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list); + } + return ret; +} + +// Copies a specified amount of characters from the list of buffered data +// chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBufferString(n, list) { + var p = list.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +// Copies a specified amount of bytes from the list of buffered data chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBuffer(n, list) { + var ret = Buffer.allocUnsafe(n); + var p = list.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + processNextTick(endReadableNT, state, stream); + } +} + +function endReadableNT(state, stream) { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } +} + +function forEach(xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./_stream_duplex":49,"./internal/streams/BufferList":54,"./internal/streams/destroy":55,"./internal/streams/stream":56,"_process":47,"core-util-is":29,"events":30,"inherits":32,"isarray":34,"process-nextick-args":46,"safe-buffer":62,"string_decoder/":57,"util":25}],52:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +'use strict'; + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(Transform, Duplex); + +function TransformState(stream) { + this.afterTransform = function (er, data) { + return afterTransform(stream, er, data); + }; + + this.needTransform = false; + this.transforming = false; + this.writecb = null; + this.writechunk = null; + this.writeencoding = null; +} + +function afterTransform(stream, er, data) { + var ts = stream._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) { + return stream.emit('error', new Error('write callback called multiple times')); + } + + ts.writechunk = null; + ts.writecb = null; + + if (data !== null && data !== undefined) stream.push(data); + + cb(er); + + var rs = stream._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + stream._read(rs.highWaterMark); + } +} + +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + + Duplex.call(this, options); + + this._transformState = new TransformState(this); + + var stream = this; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.once('prefinish', function () { + if (typeof this._flush === 'function') this._flush(function (er, data) { + done(stream, er, data); + });else done(stream); + }); +} + +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + throw new Error('_transform() is not implemented'); +}; + +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + +Transform.prototype._destroy = function (err, cb) { + var _this = this; + + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + _this.emit('close'); + }); +}; + +function done(stream, er, data) { + if (er) return stream.emit('error', er); + + if (data !== null && data !== undefined) stream.push(data); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + var ws = stream._writableState; + var ts = stream._transformState; + + if (ws.length) throw new Error('Calling transform done when ws.length != 0'); + + if (ts.transforming) throw new Error('Calling transform done when still transforming'); + + return stream.push(null); +} +},{"./_stream_duplex":49,"core-util-is":29,"inherits":32}],53:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + +'use strict'; + +/**/ + +var processNextTick = require('process-nextick-args'); +/**/ + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick; +/**/ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +/**/ +var internalUtil = { + deprecate: require('util-deprecate') +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} +/**/ + +var destroyImpl = require('./internal/streams/destroy'); + +util.inherits(Writable, Stream); + +function nop() {} + +function WritableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} + +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; + +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function () { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function (object) { + if (realHasInstance.call(this, object)) return true; + + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function (object) { + return object instanceof this; + }; +} + +function Writable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { + return new Writable(options); + } + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + if (options) { + if (typeof options.write === 'function') this._write = options.write; + + if (typeof options.writev === 'function') this._writev = options.writev; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + + if (typeof options.final === 'function') this._final = options.final; + } + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + this.emit('error', new Error('Cannot pipe, not readable')); +}; + +function writeAfterEnd(stream, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + processNextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var valid = true; + var er = false; + + if (chunk === null) { + er = new TypeError('May not write null values to stream'); + } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + if (er) { + stream.emit('error', er); + processNextTick(cb, er); + valid = false; + } + return valid; +} + +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = _isUint8Array(chunk) && !state.objectMode; + + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + + if (typeof cb !== 'function') cb = nop; + + if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function () { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function () { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; + +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + + return ret; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + processNextTick(cb, er); + // this can emit finish, and it will always happen + // after error + processNextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state); + + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + + if (sync) { + /**/ + asyncWrite(afterWrite, stream, state, finished, cb); + /**/ + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + + if (entry === null) state.lastBufferedRequest = null; + } + + state.bufferedRequestCount = 0; + state.bufferedRequest = entry; + state.bufferProcessing = false; +} + +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new Error('_write() is not implemented')); +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) endWritable(this, state, cb); +}; + +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + stream.emit('error', err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function') { + state.pendingcb++; + state.finalCalled = true; + processNextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} + +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + } + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) processNextTick(cb);else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} + +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + if (state.corkedRequestsFree) { + state.corkedRequestsFree.next = corkReq; + } else { + state.corkedRequestsFree = corkReq; + } +} + +Object.defineProperty(Writable.prototype, 'destroyed', { + get: function () { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); + +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + this.end(); + cb(err); +}; +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./_stream_duplex":49,"./internal/streams/destroy":55,"./internal/streams/stream":56,"_process":47,"core-util-is":29,"inherits":32,"process-nextick-args":46,"safe-buffer":62,"util-deprecate":64}],54:[function(require,module,exports){ +'use strict'; + +/**/ + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Buffer = require('safe-buffer').Buffer; +/**/ + +function copyBuffer(src, target, offset) { + src.copy(target, offset); +} + +module.exports = function () { + function BufferList() { + _classCallCheck(this, BufferList); + + this.head = null; + this.tail = null; + this.length = 0; + } + + BufferList.prototype.push = function push(v) { + var entry = { data: v, next: null }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + }; + + BufferList.prototype.unshift = function unshift(v) { + var entry = { data: v, next: this.head }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + }; + + BufferList.prototype.shift = function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + }; + + BufferList.prototype.clear = function clear() { + this.head = this.tail = null; + this.length = 0; + }; + + BufferList.prototype.join = function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) { + ret += s + p.data; + }return ret; + }; + + BufferList.prototype.concat = function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + if (this.length === 1) return this.head.data; + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + }; + + return BufferList; +}(); +},{"safe-buffer":62}],55:[function(require,module,exports){ +'use strict'; + +/**/ + +var processNextTick = require('process-nextick-args'); +/**/ + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err && (!this._writableState || !this._writableState.errorEmitted)) { + processNextTick(emitErrorNT, this, err); + } + return; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + + this._destroy(err || null, function (err) { + if (!cb && err) { + processNextTick(emitErrorNT, _this, err); + if (_this._writableState) { + _this._writableState.errorEmitted = true; + } + } else if (cb) { + cb(err); + } + }); +} + +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} + +function emitErrorNT(self, err) { + self.emit('error', err); +} + +module.exports = { + destroy: destroy, + undestroy: undestroy +}; +},{"process-nextick-args":46}],56:[function(require,module,exports){ +module.exports = require('events').EventEmitter; + +},{"events":30}],57:[function(require,module,exports){ +'use strict'; + +var Buffer = require('safe-buffer').Buffer; + +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.StringDecoder = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} + +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; + +StringDecoder.prototype.end = utf8End; + +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; + +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; + +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return -1; +} + +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} + +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// UTF-8 replacement characters ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'.repeat(p); + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'.repeat(p + 1); + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'.repeat(p + 2); + } + } + } +} + +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character for each buffered byte of a (partial) +// character needs to be added to the output. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'.repeat(this.lastTotal - this.lastNeed); + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} + +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} + +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} + +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} + +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} + +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} +},{"safe-buffer":62}],58:[function(require,module,exports){ +module.exports = require('./readable').PassThrough + +},{"./readable":59}],59:[function(require,module,exports){ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); + +},{"./lib/_stream_duplex.js":49,"./lib/_stream_passthrough.js":50,"./lib/_stream_readable.js":51,"./lib/_stream_transform.js":52,"./lib/_stream_writable.js":53}],60:[function(require,module,exports){ +module.exports = require('./readable').Transform + +},{"./readable":59}],61:[function(require,module,exports){ +module.exports = require('./lib/_stream_writable.js'); + +},{"./lib/_stream_writable.js":53}],62:[function(require,module,exports){ +/* 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) +} + +// 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) +} + +},{"buffer":28}],63:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Stream; + +var EE = require('events').EventEmitter; +var inherits = require('inherits'); + +inherits(Stream, EE); +Stream.Readable = require('readable-stream/readable.js'); +Stream.Writable = require('readable-stream/writable.js'); +Stream.Duplex = require('readable-stream/duplex.js'); +Stream.Transform = require('readable-stream/transform.js'); +Stream.PassThrough = require('readable-stream/passthrough.js'); + +// Backwards-compat with node 0.4.x +Stream.Stream = Stream; + + + +// old-style streams. Note that the pipe method (the only relevant +// part of this class) is overridden in the Readable class. + +function Stream() { + EE.call(this); +} + +Stream.prototype.pipe = function(dest, options) { + var source = this; + + function ondata(chunk) { + if (dest.writable) { + if (false === dest.write(chunk) && source.pause) { + source.pause(); + } + } + } + + source.on('data', ondata); + + function ondrain() { + if (source.readable && source.resume) { + source.resume(); + } + } + + dest.on('drain', ondrain); + + // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend); + source.on('close', onclose); + } + + var didOnEnd = false; + function onend() { + if (didOnEnd) return; + didOnEnd = true; + + dest.end(); + } + + + function onclose() { + if (didOnEnd) return; + didOnEnd = true; + + if (typeof dest.destroy === 'function') dest.destroy(); + } + + // don't leave dangling pipes when there are errors. + function onerror(er) { + cleanup(); + if (EE.listenerCount(this, 'error') === 0) { + throw er; // Unhandled stream error in pipe. + } + } + + source.on('error', onerror); + dest.on('error', onerror); + + // remove all the event listeners that were added. + function cleanup() { + source.removeListener('data', ondata); + dest.removeListener('drain', ondrain); + + source.removeListener('end', onend); + source.removeListener('close', onclose); + + source.removeListener('error', onerror); + dest.removeListener('error', onerror); + + source.removeListener('end', cleanup); + source.removeListener('close', cleanup); + + dest.removeListener('close', cleanup); + } + + source.on('end', cleanup); + source.on('close', cleanup); + + dest.on('close', cleanup); + + dest.emit('pipe', source); + + // Allow for unix-like usage: A.pipe(B).pipe(C) + return dest; +}; + +},{"events":30,"inherits":32,"readable-stream/duplex.js":48,"readable-stream/passthrough.js":58,"readable-stream/readable.js":59,"readable-stream/transform.js":60,"readable-stream/writable.js":61}],64:[function(require,module,exports){ +(function (global){ + +/** + * Module exports. + */ + +module.exports = deprecate; + +/** + * Mark that a method should not be used. + * Returns a modified function which warns once by default. + * + * If `localStorage.noDeprecation = true` is set, then it is a no-op. + * + * If `localStorage.throwDeprecation = true` is set, then deprecated functions + * will throw an Error when invoked. + * + * If `localStorage.traceDeprecation = true` is set, then deprecated functions + * will invoke `console.trace()` instead of `console.error()`. + * + * @param {Function} fn - the function to deprecate + * @param {String} msg - the string to print to the console when `fn` is invoked + * @returns {Function} a new "deprecated" version of `fn` + * @api public + */ + +function deprecate (fn, msg) { + if (config('noDeprecation')) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (config('throwDeprecation')) { + throw new Error(msg); + } else if (config('traceDeprecation')) { + console.trace(msg); + } else { + console.warn(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +} + +/** + * Checks `localStorage` for boolean values for the given `name`. + * + * @param {String} name + * @returns {Boolean} + * @api private + */ + +function config (name) { + // accessing global.localStorage can trigger a DOMException in sandboxed iframes + try { + if (!global.localStorage) return false; + } catch (_) { + return false; + } + var val = global.localStorage[name]; + if (null == val) return false; + return String(val).toLowerCase() === 'true'; +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],65:[function(require,module,exports){ +arguments[4][32][0].apply(exports,arguments) +},{"dup":32}],66:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],67:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = require('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":66,"_process":47,"inherits":65}]},{},[20])(20) +}); \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/base.css b/node_modules/pngjs/coverage/lcov-report/base.css new file mode 100644 index 0000000..ac7c23c --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/base.css @@ -0,0 +1,354 @@ +body, +html { + margin: 0; + padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color: #333; +} +.small { + font-size: 12px; +} +*, +*:after, +*:before { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +h1 { + font-size: 20px; + margin: 0; +} +h2 { + font-size: 14px; +} +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { + color: #0074d9; + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +.strong { + font-weight: bold; +} +.space-top1 { + padding: 10px 0 0 0; +} +.pad2y { + padding: 20px 0; +} +.pad1y { + padding: 10px 0; +} +.pad2x { + padding: 0 20px; +} +.pad2 { + padding: 20px; +} +.pad1 { + padding: 10px; +} +.space-left2 { + padding-left: 55px; +} +.space-right2 { + padding-right: 20px; +} +.center { + text-align: center; +} +.clearfix { + display: block; +} +.clearfix:after { + content: ""; + display: block; + height: 0; + clear: both; + visibility: hidden; +} +.fl { + float: left; +} +@media only screen and (max-width: 640px) { + .col3 { + width: 100%; + max-width: 100%; + } + .hide-mobile { + display: none !important; + } +} + +.quiet { + color: #7f7f7f; + color: rgba(0, 0, 0, 0.5); +} +.quiet a { + opacity: 0.7; +} + +.fraction { + font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #e8e8e8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, +div.path a:visited { + color: #333; +} +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width: 20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, +.skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { + border-bottom: 1px solid #bbb; +} +.keyline-all { + border: 1px solid #ddd; +} +.coverage-summary td, +.coverage-summary th { + padding: 10px; +} +.coverage-summary tbody { + border: 1px solid #bbb; +} +.coverage-summary td { + border-right: 1px solid #bbb; +} +.coverage-summary td:last-child { + border-right: none; +} +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { + border-right: none !important; +} +.coverage-summary th.pct { +} +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { + text-align: right; +} +.coverage-summary td.file { + white-space: nowrap; +} +.coverage-summary td.pic { + min-width: 120px !important; +} +.coverage-summary tfoot td { +} + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { + height: 10px; +} +/* yellow */ +.cbranch-no { + background: yellow !important; + color: #111; +} +/* dark red */ +.red.solid, +.status-line.low, +.low .cover-fill { + background: #c21f39; +} +.low .chart { + border: 1px solid #c21f39; +} +.highlighted, +.highlighted .cstat-no, +.highlighted .fstat-no, +.highlighted .cbranch-no { + background: #c21f39 !important; +} +/* medium red */ +.cstat-no, +.fstat-no, +.cbranch-no, +.cbranch-no { + background: #f6c6ce; +} +/* light red */ +.low, +.cline-no { + background: #fce1e5; +} +/* light green */ +.high, +.cline-yes { + background: rgb(230, 245, 208); +} +/* medium green */ +.cstat-yes { + background: rgb(161, 215, 106); +} +/* dark green */ +.status-line.high, +.high .cover-fill { + background: rgb(77, 146, 33); +} +.high .chart { + border: 1px solid rgb(77, 146, 33); +} +/* dark yellow (gold) */ +.status-line.medium, +.medium .cover-fill { + background: #f9cd0b; +} +.medium .chart { + border: 1px solid #f9cd0b; +} +/* light yellow */ +.medium { + background: #fff4c2; +} + +.cstat-skip { + background: #ddd; + color: #111; +} +.fstat-skip { + background: #ddd; + color: #111 !important; +} +.cbranch-skip { + background: #ddd !important; + color: #111; +} + +span.cline-neutral { + background: #eaeaea; +} + +.coverage-summary td.empty { + opacity: 0.5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, +.cover-empty { + display: inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { + color: #999 !important; +} +.ignore-none { + color: #999; + font-weight: normal; +} + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, +.push { + height: 48px; +} diff --git a/node_modules/pngjs/coverage/lcov-report/bitmapper.js.html b/node_modules/pngjs/coverage/lcov-report/bitmapper.js.html new file mode 100644 index 0000000..bafa89b --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/bitmapper.js.html @@ -0,0 +1,881 @@ + + + + + + Code coverage report for bitmapper.js + + + + + + + + + +
+
+

All files bitmapper.js

+
+ +
+ 94.37% + Statements + 134/142 +
+ + +
+ 72.41% + Branches + 21/29 +
+ + +
+ 89.47% + Functions + 17/19 +
+ + +
+ 94.16% + Lines + 129/137 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268  +  +1x +  +1x +  +  +  +  +  +  +313632x +  +  +  +313632x +313632x +313632x +313632x +313632x +  +  +  +  +  +8192x +  +  +  +8192x +8192x +8192x +8192x +8192x +  +  +  +  +  +1228160x +  +  +  +1228160x +1228160x +1228160x +1228160x +  +  +  +  +  +272640x +  +  +  +272640x +272640x +272640x +272640x +  +  +  +1x +  +  +  +  +  +  +1193380x +1193380x +1193380x +1193380x +1193380x +  +  +  +  +  +8192x +8192x +8192x +8192x +8192x +  +  +  +  +  +24576x +24576x +24576x +24576x +  +  +  +  +  +8192x +8192x +8192x +8192x +  +  +  +  +209x +209x +  +  +334250x +  +  +334250x +334250x +  +334250x +  +  +  +149504x +149504x +149504x +149504x +  +49612x +49612x +49612x +49612x +  +2968x +2968x +2968x +2968x +2968x +2968x +  +132166x +132166x +132166x +132166x +132166x +132166x +132166x +132166x +132166x +132166x +  +  +  +209x +  +1234340x +334250x +  +1234340x +1234340x +1234340x +  +  +8106x +  +  +209x +  +  +  +  +  +  +  +  +210x +210x +210x +210x +7288x +1822624x +1822624x +1822624x +  +  +210x +  +  +  +  +529x +529x +529x +529x +8106x +1234340x +1234340x +1234340x +  +8106x +  +  +  +1x +335x +335x +335x +335x +335x +  +  +335x +209x +  +  +335x +269x +  +66x +  +335x +335x +  +  +  +335x +72x +72x +  +263x +263x +2732114x +2732114x +2732114x +  +263x +  +  +335x +739x +210x +  +  +  +  +  +  +  +  +529x +  +  +  +  +  +  +  +  +  +335x +126x +  +  +  +209x +  +  +335x +  + 
"use strict";
+ 
+let interlaceUtils = require("./interlace");
+ 
+let pixelBppMapper = [
+  // 0 - dummy entry
+  function () {},
+ 
+  // 1 - L
+  // 0: 0, 1: 0, 2: 0, 3: 0xff
+  function (pxData, data, pxPos, rawPos) {
+    Iif (rawPos === data.length) {
+      throw new Error("Ran out of data");
+    }
+ 
+    let pixel = data[rawPos];
+    pxData[pxPos] = pixel;
+    pxData[pxPos + 1] = pixel;
+    pxData[pxPos + 2] = pixel;
+    pxData[pxPos + 3] = 0xff;
+  },
+ 
+  // 2 - LA
+  // 0: 0, 1: 0, 2: 0, 3: 1
+  function (pxData, data, pxPos, rawPos) {
+    Iif (rawPos + 1 >= data.length) {
+      throw new Error("Ran out of data");
+    }
+ 
+    let pixel = data[rawPos];
+    pxData[pxPos] = pixel;
+    pxData[pxPos + 1] = pixel;
+    pxData[pxPos + 2] = pixel;
+    pxData[pxPos + 3] = data[rawPos + 1];
+  },
+ 
+  // 3 - RGB
+  // 0: 0, 1: 1, 2: 2, 3: 0xff
+  function (pxData, data, pxPos, rawPos) {
+    Iif (rawPos + 2 >= data.length) {
+      throw new Error("Ran out of data");
+    }
+ 
+    pxData[pxPos] = data[rawPos];
+    pxData[pxPos + 1] = data[rawPos + 1];
+    pxData[pxPos + 2] = data[rawPos + 2];
+    pxData[pxPos + 3] = 0xff;
+  },
+ 
+  // 4 - RGBA
+  // 0: 0, 1: 1, 2: 2, 3: 3
+  function (pxData, data, pxPos, rawPos) {
+    Iif (rawPos + 3 >= data.length) {
+      throw new Error("Ran out of data");
+    }
+ 
+    pxData[pxPos] = data[rawPos];
+    pxData[pxPos + 1] = data[rawPos + 1];
+    pxData[pxPos + 2] = data[rawPos + 2];
+    pxData[pxPos + 3] = data[rawPos + 3];
+  },
+];
+ 
+let pixelBppCustomMapper = [
+  // 0 - dummy entry
+  function () {},
+ 
+  // 1 - L
+  // 0: 0, 1: 0, 2: 0, 3: 0xff
+  function (pxData, pixelData, pxPos, maxBit) {
+    let pixel = pixelData[0];
+    pxData[pxPos] = pixel;
+    pxData[pxPos + 1] = pixel;
+    pxData[pxPos + 2] = pixel;
+    pxData[pxPos + 3] = maxBit;
+  },
+ 
+  // 2 - LA
+  // 0: 0, 1: 0, 2: 0, 3: 1
+  function (pxData, pixelData, pxPos) {
+    let pixel = pixelData[0];
+    pxData[pxPos] = pixel;
+    pxData[pxPos + 1] = pixel;
+    pxData[pxPos + 2] = pixel;
+    pxData[pxPos + 3] = pixelData[1];
+  },
+ 
+  // 3 - RGB
+  // 0: 0, 1: 1, 2: 2, 3: 0xff
+  function (pxData, pixelData, pxPos, maxBit) {
+    pxData[pxPos] = pixelData[0];
+    pxData[pxPos + 1] = pixelData[1];
+    pxData[pxPos + 2] = pixelData[2];
+    pxData[pxPos + 3] = maxBit;
+  },
+ 
+  // 4 - RGBA
+  // 0: 0, 1: 1, 2: 2, 3: 3
+  function (pxData, pixelData, pxPos) {
+    pxData[pxPos] = pixelData[0];
+    pxData[pxPos + 1] = pixelData[1];
+    pxData[pxPos + 2] = pixelData[2];
+    pxData[pxPos + 3] = pixelData[3];
+  },
+];
+ 
+function bitRetriever(data, depth) {
+  let leftOver = [];
+  let i = 0;
+ 
+  function split() {
+    Iif (i === data.length) {
+      throw new Error("Ran out of data");
+    }
+    let byte = data[i];
+    i++;
+    let byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1;
+    switch (depth) {
+      default:
+        throw new Error("unrecognised depth");
+      case 16:
+        byte2 = data[i];
+        i++;
+        leftOver.push((byte << 8) + byte2);
+        break;
+      case 4:
+        byte2 = byte & 0x0f;
+        byte1 = byte >> 4;
+        leftOver.push(byte1, byte2);
+        break;
+      case 2:
+        byte4 = byte & 3;
+        byte3 = (byte >> 2) & 3;
+        byte2 = (byte >> 4) & 3;
+        byte1 = (byte >> 6) & 3;
+        leftOver.push(byte1, byte2, byte3, byte4);
+        break;
+      case 1:
+        byte8 = byte & 1;
+        byte7 = (byte >> 1) & 1;
+        byte6 = (byte >> 2) & 1;
+        byte5 = (byte >> 3) & 1;
+        byte4 = (byte >> 4) & 1;
+        byte3 = (byte >> 5) & 1;
+        byte2 = (byte >> 6) & 1;
+        byte1 = (byte >> 7) & 1;
+        leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8);
+        break;
+    }
+  }
+ 
+  return {
+    get: function (count) {
+      while (leftOver.length < count) {
+        split();
+      }
+      let returner = leftOver.slice(0, count);
+      leftOver = leftOver.slice(count);
+      return returner;
+    },
+    resetAfterLine: function () {
+      leftOver.length = 0;
+    },
+    end: function () {
+      Iif (i !== data.length) {
+        throw new Error("extra data found");
+      }
+    },
+  };
+}
+ 
+function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) {
+  // eslint-disable-line max-params
+  let imageWidth = image.width;
+  let imageHeight = image.height;
+  let imagePass = image.index;
+  for (let y = 0; y < imageHeight; y++) {
+    for (let x = 0; x < imageWidth; x++) {
+      let pxPos = getPxPos(x, y, imagePass);
+      pixelBppMapper[bpp](pxData, data, pxPos, rawPos);
+      rawPos += bpp; //eslint-disable-line no-param-reassign
+    }
+  }
+  return rawPos;
+}
+ 
+function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) {
+  // eslint-disable-line max-params
+  let imageWidth = image.width;
+  let imageHeight = image.height;
+  let imagePass = image.index;
+  for (let y = 0; y < imageHeight; y++) {
+    for (let x = 0; x < imageWidth; x++) {
+      let pixelData = bits.get(bpp);
+      let pxPos = getPxPos(x, y, imagePass);
+      pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit);
+    }
+    bits.resetAfterLine();
+  }
+}
+ 
+exports.dataToBitMap = function (data, bitmapInfo) {
+  let width = bitmapInfo.width;
+  let height = bitmapInfo.height;
+  let depth = bitmapInfo.depth;
+  let bpp = bitmapInfo.bpp;
+  let interlace = bitmapInfo.interlace;
+  let bits;
+ 
+  if (depth !== 8) {
+    bits = bitRetriever(data, depth);
+  }
+  let pxData;
+  if (depth <= 8) {
+    pxData = Buffer.alloc(width * height * 4);
+  } else {
+    pxData = new Uint16Array(width * height * 4);
+  }
+  let maxBit = Math.pow(2, depth) - 1;
+  let rawPos = 0;
+  let images;
+  let getPxPos;
+ 
+  if (interlace) {
+    images = interlaceUtils.getImagePasses(width, height);
+    getPxPos = interlaceUtils.getInterlaceIterator(width, height);
+  } else {
+    let nonInterlacedPxPos = 0;
+    getPxPos = function () {
+      let returner = nonInterlacedPxPos;
+      nonInterlacedPxPos += 4;
+      return returner;
+    };
+    images = [{ width: width, height: height }];
+  }
+ 
+  for (let imageIndex = 0; imageIndex < images.length; imageIndex++) {
+    if (depth === 8) {
+      rawPos = mapImage8Bit(
+        images[imageIndex],
+        pxData,
+        getPxPos,
+        bpp,
+        data,
+        rawPos
+      );
+    } else {
+      mapImageCustomBit(
+        images[imageIndex],
+        pxData,
+        getPxPos,
+        bpp,
+        bits,
+        maxBit
+      );
+    }
+  }
+  if (depth === 8) {
+    Iif (rawPos !== data.length) {
+      throw new Error("extra data found");
+    }
+  } else {
+    bits.end();
+  }
+ 
+  return pxData;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html b/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html new file mode 100644 index 0000000..50cca23 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html @@ -0,0 +1,554 @@ + + + + + + Code coverage report for bitpacker.js + + + + + + + + + +
+
+

All files bitpacker.js

+
+ +
+ 11.36% + Statements + 10/88 +
+ + +
+ 6.12% + Branches + 3/49 +
+ + +
+ 66.67% + Functions + 2/3 +
+ + +
+ 11.63% + Lines + 10/86 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159  +  +1x +  +1x +  +325x +  +  +325x +325x +325x +325x +  +325x +  +  +325x +325x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
"use strict";
+ 
+let constants = require("./constants");
+ 
+module.exports = function (dataIn, width, height, options) {
+  let outHasAlpha =
+    [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(
+      options.colorType
+    ) !== -1;
+  Eif (options.colorType === options.inputColorType) {
+    let bigEndian = (function () {
+      let buffer = new ArrayBuffer(2);
+      new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
+      // Int16Array uses the platform's endianness.
+      return new Int16Array(buffer)[0] !== 256;
+    })();
+    // If no need to convert to grayscale and alpha is present/absent in both, take a fast route
+    Eif (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) {
+      return dataIn;
+    }
+  }
+ 
+  // map to a UInt16 array if data is 16bit, fix endianness below
+  let data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
+ 
+  let maxValue = 255;
+  let inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType];
+  if (inBpp === 4 && !options.inputHasAlpha) {
+    inBpp = 3;
+  }
+  let outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType];
+  if (options.bitDepth === 16) {
+    maxValue = 65535;
+    outBpp *= 2;
+  }
+  let outData = Buffer.alloc(width * height * outBpp);
+ 
+  let inIndex = 0;
+  let outIndex = 0;
+ 
+  let bgColor = options.bgColor || {};
+  if (bgColor.red === undefined) {
+    bgColor.red = maxValue;
+  }
+  if (bgColor.green === undefined) {
+    bgColor.green = maxValue;
+  }
+  if (bgColor.blue === undefined) {
+    bgColor.blue = maxValue;
+  }
+ 
+  function getRGBA() {
+    let red;
+    let green;
+    let blue;
+    let alpha = maxValue;
+    switch (options.inputColorType) {
+      case constants.COLORTYPE_COLOR_ALPHA:
+        alpha = data[inIndex + 3];
+        red = data[inIndex];
+        green = data[inIndex + 1];
+        blue = data[inIndex + 2];
+        break;
+      case constants.COLORTYPE_COLOR:
+        red = data[inIndex];
+        green = data[inIndex + 1];
+        blue = data[inIndex + 2];
+        break;
+      case constants.COLORTYPE_ALPHA:
+        alpha = data[inIndex + 1];
+        red = data[inIndex];
+        green = red;
+        blue = red;
+        break;
+      case constants.COLORTYPE_GRAYSCALE:
+        red = data[inIndex];
+        green = red;
+        blue = red;
+        break;
+      default:
+        throw new Error(
+          "input color type:" +
+            options.inputColorType +
+            " is not supported at present"
+        );
+    }
+ 
+    if (options.inputHasAlpha) {
+      if (!outHasAlpha) {
+        alpha /= maxValue;
+        red = Math.min(
+          Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0),
+          maxValue
+        );
+        green = Math.min(
+          Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0),
+          maxValue
+        );
+        blue = Math.min(
+          Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0),
+          maxValue
+        );
+      }
+    }
+    return { red: red, green: green, blue: blue, alpha: alpha };
+  }
+ 
+  for (let y = 0; y < height; y++) {
+    for (let x = 0; x < width; x++) {
+      let rgba = getRGBA(data, inIndex);
+ 
+      switch (options.colorType) {
+        case constants.COLORTYPE_COLOR_ALPHA:
+        case constants.COLORTYPE_COLOR:
+          if (options.bitDepth === 8) {
+            outData[outIndex] = rgba.red;
+            outData[outIndex + 1] = rgba.green;
+            outData[outIndex + 2] = rgba.blue;
+            if (outHasAlpha) {
+              outData[outIndex + 3] = rgba.alpha;
+            }
+          } else {
+            outData.writeUInt16BE(rgba.red, outIndex);
+            outData.writeUInt16BE(rgba.green, outIndex + 2);
+            outData.writeUInt16BE(rgba.blue, outIndex + 4);
+            if (outHasAlpha) {
+              outData.writeUInt16BE(rgba.alpha, outIndex + 6);
+            }
+          }
+          break;
+        case constants.COLORTYPE_ALPHA:
+        case constants.COLORTYPE_GRAYSCALE: {
+          // Convert to grayscale and alpha
+          let grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
+          if (options.bitDepth === 8) {
+            outData[outIndex] = grayscale;
+            if (outHasAlpha) {
+              outData[outIndex + 1] = rgba.alpha;
+            }
+          } else {
+            outData.writeUInt16BE(grayscale, outIndex);
+            if (outHasAlpha) {
+              outData.writeUInt16BE(rgba.alpha, outIndex + 2);
+            }
+          }
+          break;
+        }
+        default:
+          throw new Error("unrecognised color Type " + options.colorType);
+      }
+ 
+      inIndex += inBpp;
+      outIndex += outBpp;
+    }
+  }
+ 
+  return outData;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/block-navigation.js b/node_modules/pngjs/coverage/lcov-report/block-navigation.js new file mode 100644 index 0000000..81d08c0 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/block-navigation.js @@ -0,0 +1,77 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = [".cbranch-no", ".cstat-no", ".fstat-no"]; + + // Elements to highlight in the file listing view + var fileListingElements = ["td.pct.low"]; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ":not(" + missingCoverageClasses.join("):not(") + ") > "; // becomes `:not(a):not(b) > ` + + // Selecter that finds elements on the page to which we can jump + var selector = + fileListingElements.join(", ") + + ", " + + notSelector + + missingCoverageClasses.join(", " + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements.item(currentIndex).classList.remove("highlighted"); + missingCoverageElements.item(index).classList.add("highlighted"); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: "smooth", + block: "center", + inline: "center", + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== "number" || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === "number" && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener("keydown", jumpToCode); diff --git a/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html b/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html new file mode 100644 index 0000000..552ffba --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html @@ -0,0 +1,647 @@ + + + + + + Code coverage report for chunkstream.js + + + + + + + + + +
+
+

All files chunkstream.js

+
+ +
+ 90.11% + Statements + 82/91 +
+ + +
+ 81.4% + Branches + 35/43 +
+ + +
+ 100% + Functions + 10/10 +
+ + +
+ 90.11% + Lines + 82/91 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190  +  +1x +1x +  +1x +529x +  +529x +529x +  +529x +529x +  +529x +529x +  +1x +  +1x +13318x +  +  +  +  +  +13318x +  +13318x +  +  +13318x +  +  +  +  +  +  +  +  +1x +943x +  +  +  +  +  +943x +943x +  +  +  +  +943x +943x +  +943x +  +  +943x +346x +  +  +943x +  +  +1x +311x +  +  +  +311x +  +  +311x +  +  +  +  +311x +309x +  +2x +2x +  +  +  +1x +  +1x +311x +3x +  +  +311x +  +  +1x +327x +  +  +  +327x +327x +327x +  +327x +  +  +1x +  +741x +  +  +741x +  +  +741x +568x +568x +  +568x +  +  +173x +173x +  +173x +  +  +  +1x +12408x +  +12408x +12408x +12408x +  +  +12408x +12617x +12617x +  +12617x +12617x +  +  +12617x +11863x +  +  +  +  +12408x +532x +  +  +12408x +  +12408x +  +  +1x +14263x +  +14263x +15656x +  +  +15656x +741x +14915x +  +  +12408x +  +  +  +2507x +  +  +  +14263x +2x +  +  +  +  +  + 
"use strict";
+ 
+let util = require("util");
+let Stream = require("stream");
+ 
+let ChunkStream = (module.exports = function () {
+  Stream.call(this);
+ 
+  this._buffers = [];
+  this._buffered = 0;
+ 
+  this._reads = [];
+  this._paused = false;
+ 
+  this._encoding = "utf8";
+  this.writable = true;
+});
+util.inherits(ChunkStream, Stream);
+ 
+ChunkStream.prototype.read = function (length, callback) {
+  this._reads.push({
+    length: Math.abs(length), // if length < 0 then at most this length
+    allowLess: length < 0,
+    func: callback,
+  });
+ 
+  process.nextTick(
+    function () {
+      this._process();
+ 
+      // its paused and there is not enought data then ask for more
+      Iif (this._paused && this._reads.length > 0) {
+        this._paused = false;
+ 
+        this.emit("drain");
+      }
+    }.bind(this)
+  );
+};
+ 
+ChunkStream.prototype.write = function (data, encoding) {
+  Iif (!this.writable) {
+    this.emit("error", new Error("Stream not writable"));
+    return false;
+  }
+ 
+  let dataBuffer;
+  Eif (Buffer.isBuffer(data)) {
+    dataBuffer = data;
+  } else {
+    dataBuffer = Buffer.from(data, encoding || this._encoding);
+  }
+ 
+  this._buffers.push(dataBuffer);
+  this._buffered += dataBuffer.length;
+ 
+  this._process();
+ 
+  // ok if there are no more read requests
+  if (this._reads && this._reads.length === 0) {
+    this._paused = true;
+  }
+ 
+  return this.writable && !this._paused;
+};
+ 
+ChunkStream.prototype.end = function (data, encoding) {
+  Iif (data) {
+    this.write(data, encoding);
+  }
+ 
+  this.writable = false;
+ 
+  // already destroyed
+  Iif (!this._buffers) {
+    return;
+  }
+ 
+  // enqueue or handle end
+  if (this._buffers.length === 0) {
+    this._end();
+  } else {
+    this._buffers.push(null);
+    this._process();
+  }
+};
+ 
+ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
+ 
+ChunkStream.prototype._end = function () {
+  if (this._reads.length > 0) {
+    this.emit("error", new Error("Unexpected end of input"));
+  }
+ 
+  this.destroy();
+};
+ 
+ChunkStream.prototype.destroy = function () {
+  Iif (!this._buffers) {
+    return;
+  }
+ 
+  this.writable = false;
+  this._reads = null;
+  this._buffers = null;
+ 
+  this.emit("close");
+};
+ 
+ChunkStream.prototype._processReadAllowingLess = function (read) {
+  // ok there is any data so that we can satisfy this request
+  this._reads.shift(); // == read
+ 
+  // first we need to peek into first buffer
+  let smallerBuf = this._buffers[0];
+ 
+  // ok there is more data than we need
+  if (smallerBuf.length > read.length) {
+    this._buffered -= read.length;
+    this._buffers[0] = smallerBuf.slice(read.length);
+ 
+    read.func.call(this, smallerBuf.slice(0, read.length));
+  } else {
+    // ok this is less than maximum length so use it all
+    this._buffered -= smallerBuf.length;
+    this._buffers.shift(); // == smallerBuf
+ 
+    read.func.call(this, smallerBuf);
+  }
+};
+ 
+ChunkStream.prototype._processRead = function (read) {
+  this._reads.shift(); // == read
+ 
+  let pos = 0;
+  let count = 0;
+  let data = Buffer.alloc(read.length);
+ 
+  // create buffer for all data
+  while (pos < read.length) {
+    let buf = this._buffers[count++];
+    let len = Math.min(buf.length, read.length - pos);
+ 
+    buf.copy(data, pos, 0, len);
+    pos += len;
+ 
+    // last buffer wasn't used all so just slice it and leave
+    if (len !== buf.length) {
+      this._buffers[--count] = buf.slice(len);
+    }
+  }
+ 
+  // remove all used buffers
+  if (count > 0) {
+    this._buffers.splice(0, count);
+  }
+ 
+  this._buffered -= read.length;
+ 
+  read.func.call(this, data);
+};
+ 
+ChunkStream.prototype._process = function () {
+  try {
+    // as long as there is any data and read requests
+    while (this._buffered > 0 && this._reads && this._reads.length > 0) {
+      let read = this._reads[0];
+ 
+      // read any data (but no more than length)
+      if (read.allowLess) {
+        this._processReadAllowingLess(read);
+      } else if (this._buffered >= read.length) {
+        // ok we can meet some expectations
+ 
+        this._processRead(read);
+      } else {
+        // not enought data to satisfy first request in queue
+        // so we need to wait for more
+        break;
+      }
+    }
+ 
+    if (this._buffers && !this.writable) {
+      this._end();
+    }
+  } catch (ex) {
+    this.emit("error", ex);
+  }
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/constants.js.html b/node_modules/pngjs/coverage/lcov-report/constants.js.html new file mode 100644 index 0000000..a6edd80 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/constants.js.html @@ -0,0 +1,176 @@ + + + + + + Code coverage report for constants.js + + + + + + + + + +
+
+

All files constants.js

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
"use strict";
+ 
+module.exports = {
+  PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
+ 
+  TYPE_IHDR: 0x49484452,
+  TYPE_IEND: 0x49454e44,
+  TYPE_IDAT: 0x49444154,
+  TYPE_PLTE: 0x504c5445,
+  TYPE_tRNS: 0x74524e53, // eslint-disable-line camelcase
+  TYPE_gAMA: 0x67414d41, // eslint-disable-line camelcase
+ 
+  // color-type bits
+  COLORTYPE_GRAYSCALE: 0,
+  COLORTYPE_PALETTE: 1,
+  COLORTYPE_COLOR: 2,
+  COLORTYPE_ALPHA: 4, // e.g. grayscale and alpha
+ 
+  // color-type combinations
+  COLORTYPE_PALETTE_COLOR: 3,
+  COLORTYPE_COLOR_ALPHA: 6,
+ 
+  COLORTYPE_TO_BPP_MAP: {
+    0: 1,
+    2: 3,
+    3: 1,
+    4: 2,
+    6: 4,
+  },
+ 
+  GAMMA_DIVISION: 100000,
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/crc.js.html b/node_modules/pngjs/coverage/lcov-report/crc.js.html new file mode 100644 index 0000000..53fc72a --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/crc.js.html @@ -0,0 +1,200 @@ + + + + + + Code coverage report for crc.js + + + + + + + + + +
+
+

All files crc.js

+
+ +
+ 100% + Statements + 26/26 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 5/5 +
+ + +
+ 100% + Lines + 22/22 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41  +  +1x +  +1x +1x +256x +256x +2048x +1024x +  +1024x +  +  +256x +  +  +  +1x +2461x +  +  +1x +4839x +823519x +  +4839x +  +  +1x +2195x +  +  +1x +1592x +1592x +305287x +  +1592x +  + 
"use strict";
+ 
+let crcTable = [];
+ 
+(function () {
+  for (let i = 0; i < 256; i++) {
+    let currentCrc = i;
+    for (let j = 0; j < 8; j++) {
+      if (currentCrc & 1) {
+        currentCrc = 0xedb88320 ^ (currentCrc >>> 1);
+      } else {
+        currentCrc = currentCrc >>> 1;
+      }
+    }
+    crcTable[i] = currentCrc;
+  }
+})();
+ 
+let CrcCalculator = (module.exports = function () {
+  this._crc = -1;
+});
+ 
+CrcCalculator.prototype.write = function (data) {
+  for (let i = 0; i < data.length; i++) {
+    this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8);
+  }
+  return true;
+};
+ 
+CrcCalculator.prototype.crc32 = function () {
+  return this._crc ^ -1;
+};
+ 
+CrcCalculator.crc32 = function (buf) {
+  let crc = -1;
+  for (let i = 0; i < buf.length; i++) {
+    crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
+  }
+  return crc ^ -1;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/favicon.png b/node_modules/pngjs/coverage/lcov-report/favicon.png new file mode 100644 index 0000000..6691817 Binary files /dev/null and b/node_modules/pngjs/coverage/lcov-report/favicon.png differ diff --git a/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html b/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html new file mode 100644 index 0000000..e718a1a --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html @@ -0,0 +1,593 @@ + + + + + + Code coverage report for filter-pack.js + + + + + + + + + +
+
+

All files filter-pack.js

+
+ +
+ 95.83% + Statements + 92/96 +
+ + +
+ 81.82% + Branches + 36/44 +
+ + +
+ 100% + Functions + 11/11 +
+ + +
+ 95.24% + Lines + 80/84 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172  +  +1x +  +  +44x +5136x +  +  +  +  +10490x +10490x +  +10490x +2776736x +  +10490x +  +  +  +637x +107032x +107032x +  +107032x +  +  +  +  +10490x +10490x +2776736x +2776736x +  +2776736x +  +  +10490x +  +  +  +2670x +581344x +581344x +  +581344x +  +  +  +  +10490x +10490x +10490x +2776736x +2776736x +  +2776736x +  +  +10490x +  +  +  +208x +204096x +204096x +204096x +  +204096x +  +  +  +  +10490x +10490x +2776736x +2776736x +2776736x +  +2776736x +  +  +10490x +  +  +  +6931x +1879128x +1879128x +  +1879128x +1879128x +  +1879128x +  +  +  +  +10490x +10490x +2776736x +2776736x +  +2776736x +2776736x +  +2776736x +  +  +10490x +  +  +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +  +325x +325x +  +  +  +  +  +  +325x +  +  +325x +325x +325x +325x +  +325x +  +325x +10490x +  +10490x +  +10490x +52450x +52450x +35370x +35370x +  +  +  +  +10490x +10490x +10490x +10490x +10490x +  +325x +  + 
"use strict";
+ 
+let paethPredictor = require("./paeth-predictor");
+ 
+function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) {
+  for (let x = 0; x < byteWidth; x++) {
+    rawData[rawPos + x] = pxData[pxPos + x];
+  }
+}
+ 
+function filterSumNone(pxData, pxPos, byteWidth) {
+  let sum = 0;
+  let length = pxPos + byteWidth;
+ 
+  for (let i = pxPos; i < length; i++) {
+    sum += Math.abs(pxData[i]);
+  }
+  return sum;
+}
+ 
+function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let val = pxData[pxPos + x] - left;
+ 
+    rawData[rawPos + x] = val;
+  }
+}
+ 
+function filterSumSub(pxData, pxPos, byteWidth, bpp) {
+  let sum = 0;
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let val = pxData[pxPos + x] - left;
+ 
+    sum += Math.abs(val);
+  }
+ 
+  return sum;
+}
+ 
+function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) {
+  for (let x = 0; x < byteWidth; x++) {
+    let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+    let val = pxData[pxPos + x] - up;
+ 
+    rawData[rawPos + x] = val;
+  }
+}
+ 
+function filterSumUp(pxData, pxPos, byteWidth) {
+  let sum = 0;
+  let length = pxPos + byteWidth;
+  for (let x = pxPos; x < length; x++) {
+    let up = pxPos > 0 ? pxData[x - byteWidth] : 0;
+    let val = pxData[x] - up;
+ 
+    sum += Math.abs(val);
+  }
+ 
+  return sum;
+}
+ 
+function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+    let val = pxData[pxPos + x] - ((left + up) >> 1);
+ 
+    rawData[rawPos + x] = val;
+  }
+}
+ 
+function filterSumAvg(pxData, pxPos, byteWidth, bpp) {
+  let sum = 0;
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+    let val = pxData[pxPos + x] - ((left + up) >> 1);
+ 
+    sum += Math.abs(val);
+  }
+ 
+  return sum;
+}
+ 
+function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+    let upleft =
+      pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
+    let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
+ 
+    rawData[rawPos + x] = val;
+  }
+}
+ 
+function filterSumPaeth(pxData, pxPos, byteWidth, bpp) {
+  let sum = 0;
+  for (let x = 0; x < byteWidth; x++) {
+    let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
+    let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
+    let upleft =
+      pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
+    let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
+ 
+    sum += Math.abs(val);
+  }
+ 
+  return sum;
+}
+ 
+let filters = {
+  0: filterNone,
+  1: filterSub,
+  2: filterUp,
+  3: filterAvg,
+  4: filterPaeth,
+};
+ 
+let filterSums = {
+  0: filterSumNone,
+  1: filterSumSub,
+  2: filterSumUp,
+  3: filterSumAvg,
+  4: filterSumPaeth,
+};
+ 
+module.exports = function (pxData, width, height, options, bpp) {
+  let filterTypes;
+  Eif (!("filterType" in options) || options.filterType === -1) {
+    filterTypes = [0, 1, 2, 3, 4];
+  } else if (typeof options.filterType === "number") {
+    filterTypes = [options.filterType];
+  } else {
+    throw new Error("unrecognised filter types");
+  }
+ 
+  Iif (options.bitDepth === 16) {
+    bpp *= 2;
+  }
+  let byteWidth = width * bpp;
+  let rawPos = 0;
+  let pxPos = 0;
+  let rawData = Buffer.alloc((byteWidth + 1) * height);
+ 
+  let sel = filterTypes[0];
+ 
+  for (let y = 0; y < height; y++) {
+    Eif (filterTypes.length > 1) {
+      // find best filter for this line (with lowest sum of values)
+      let min = Infinity;
+ 
+      for (let i = 0; i < filterTypes.length; i++) {
+        let sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth, bpp);
+        if (sum < min) {
+          sel = filterTypes[i];
+          min = sum;
+        }
+      }
+    }
+ 
+    rawData[rawPos] = sel;
+    rawPos++;
+    filters[sel](pxData, pxPos, byteWidth, rawData, rawPos, bpp);
+    rawPos += byteWidth;
+    pxPos += byteWidth;
+  }
+  return rawData;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html b/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html new file mode 100644 index 0000000..06f25f1 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html @@ -0,0 +1,152 @@ + + + + + + Code coverage report for filter-parse-async.js + + + + + + + + + +
+
+

All files filter-parse-async.js

+
+ +
+ 100% + Statements + 12/12 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 12/12 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25  +  +1x +1x +1x +  +1x +176x +  +176x +176x +176x +  +  +9057x +  +  +173x +  +  +  +176x +  +1x + 
"use strict";
+ 
+let util = require("util");
+let ChunkStream = require("./chunkstream");
+let Filter = require("./filter-parse");
+ 
+let FilterAsync = (module.exports = function (bitmapInfo) {
+  ChunkStream.call(this);
+ 
+  let buffers = [];
+  let that = this;
+  this._filter = new Filter(bitmapInfo, {
+    read: this.read.bind(this),
+    write: function (buffer) {
+      buffers.push(buffer);
+    },
+    complete: function () {
+      that.emit("complete", Buffer.concat(buffers));
+    },
+  });
+ 
+  this._filter.start();
+});
+util.inherits(FilterAsync, ChunkStream);
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html b/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html new file mode 100644 index 0000000..df91a35 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html @@ -0,0 +1,143 @@ + + + + + + Code coverage report for filter-parse-sync.js + + + + + + + + + +
+
+

All files filter-parse-sync.js

+
+ +
+ 100% + Statements + 10/10 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 10/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22  +  +1x +1x +  +1x +162x +162x +162x +  +  +6337x +  +  +  +  +162x +162x +  +162x +  + 
"use strict";
+ 
+let SyncReader = require("./sync-reader");
+let Filter = require("./filter-parse");
+ 
+exports.process = function (inBuffer, bitmapInfo) {
+  let outBuffers = [];
+  let reader = new SyncReader(inBuffer);
+  let filter = new Filter(bitmapInfo, {
+    read: reader.read.bind(reader),
+    write: function (bufferPart) {
+      outBuffers.push(bufferPart);
+    },
+    complete: function () {},
+  });
+ 
+  filter.start();
+  reader.process();
+ 
+  return Buffer.concat(outBuffers);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html b/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html new file mode 100644 index 0000000..945757c --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html @@ -0,0 +1,611 @@ + + + + + + Code coverage report for filter-parse.js + + + + + + + + + +
+
+

All files filter-parse.js

+
+ +
+ 98.96% + Statements + 95/96 +
+ + +
+ 97.14% + Branches + 34/35 +
+ + +
+ 100% + Functions + 8/8 +
+ + +
+ 98.9% + Lines + 90/91 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178  +  +1x +1x +  +  +742x +742x +531x +  +742x +  +  +1x +338x +338x +338x +338x +338x +  +338x +338x +338x +  +338x +338x +338x +72x +72x +476x +  +  +  +  +  +  +266x +  +  +  +  +  +  +  +  +  +  +338x +127x +211x +66x +  +145x +  +  +  +1x +338x +  +  +  +  +  +1x +  +  +  +  +1939x +1939x +  +1939x +3563504x +3563504x +3563504x +  +  +  +1x +  +  +  +  +800x +  +800x +330256x +330256x +330256x +  +  +  +1x +  +  +  +  +172x +172x +172x +  +172x +9952x +9952x +9952x +9952x +9952x +  +  +  +1x +  +  +  +  +4165x +4165x +4165x +  +4165x +1152544x +1152544x +1152544x +1152544x +1152544x +1152544x +  +  +  +1x +15394x +  +15394x +15394x +  +15394x +8318x +  +7076x +  +7076x +  +1939x +1939x +  +800x +800x +  +172x +172x +  +4165x +4165x +  +  +  +  +  +15394x +  +15394x +15394x +739x +739x +739x +  +14655x +  +  +15394x +  +15059x +  +335x +335x +  +  + 
"use strict";
+ 
+let interlaceUtils = require("./interlace");
+let paethPredictor = require("./paeth-predictor");
+ 
+function getByteWidth(width, bpp, depth) {
+  let byteWidth = width * bpp;
+  if (depth !== 8) {
+    byteWidth = Math.ceil(byteWidth / (8 / depth));
+  }
+  return byteWidth;
+}
+ 
+let Filter = (module.exports = function (bitmapInfo, dependencies) {
+  let width = bitmapInfo.width;
+  let height = bitmapInfo.height;
+  let interlace = bitmapInfo.interlace;
+  let bpp = bitmapInfo.bpp;
+  let depth = bitmapInfo.depth;
+ 
+  this.read = dependencies.read;
+  this.write = dependencies.write;
+  this.complete = dependencies.complete;
+ 
+  this._imageIndex = 0;
+  this._images = [];
+  if (interlace) {
+    let passes = interlaceUtils.getImagePasses(width, height);
+    for (let i = 0; i < passes.length; i++) {
+      this._images.push({
+        byteWidth: getByteWidth(passes[i].width, bpp, depth),
+        height: passes[i].height,
+        lineIndex: 0,
+      });
+    }
+  } else {
+    this._images.push({
+      byteWidth: getByteWidth(width, bpp, depth),
+      height: height,
+      lineIndex: 0,
+    });
+  }
+ 
+  // when filtering the line we look at the pixel to the left
+  // the spec also says it is done on a byte level regardless of the number of pixels
+  // so if the depth is byte compatible (8 or 16) we subtract the bpp in order to compare back
+  // a pixel rather than just a different byte part. However if we are sub byte, we ignore.
+  if (depth === 8) {
+    this._xComparison = bpp;
+  } else if (depth === 16) {
+    this._xComparison = bpp * 2;
+  } else {
+    this._xComparison = 1;
+  }
+});
+ 
+Filter.prototype.start = function () {
+  this.read(
+    this._images[this._imageIndex].byteWidth + 1,
+    this._reverseFilterLine.bind(this)
+  );
+};
+ 
+Filter.prototype._unFilterType1 = function (
+  rawData,
+  unfilteredLine,
+  byteWidth
+) {
+  let xComparison = this._xComparison;
+  let xBiggerThan = xComparison - 1;
+ 
+  for (let x = 0; x < byteWidth; x++) {
+    let rawByte = rawData[1 + x];
+    let f1Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
+    unfilteredLine[x] = rawByte + f1Left;
+  }
+};
+ 
+Filter.prototype._unFilterType2 = function (
+  rawData,
+  unfilteredLine,
+  byteWidth
+) {
+  let lastLine = this._lastLine;
+ 
+  for (let x = 0; x < byteWidth; x++) {
+    let rawByte = rawData[1 + x];
+    let f2Up = lastLine ? lastLine[x] : 0;
+    unfilteredLine[x] = rawByte + f2Up;
+  }
+};
+ 
+Filter.prototype._unFilterType3 = function (
+  rawData,
+  unfilteredLine,
+  byteWidth
+) {
+  let xComparison = this._xComparison;
+  let xBiggerThan = xComparison - 1;
+  let lastLine = this._lastLine;
+ 
+  for (let x = 0; x < byteWidth; x++) {
+    let rawByte = rawData[1 + x];
+    let f3Up = lastLine ? lastLine[x] : 0;
+    let f3Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
+    let f3Add = Math.floor((f3Left + f3Up) / 2);
+    unfilteredLine[x] = rawByte + f3Add;
+  }
+};
+ 
+Filter.prototype._unFilterType4 = function (
+  rawData,
+  unfilteredLine,
+  byteWidth
+) {
+  let xComparison = this._xComparison;
+  let xBiggerThan = xComparison - 1;
+  let lastLine = this._lastLine;
+ 
+  for (let x = 0; x < byteWidth; x++) {
+    let rawByte = rawData[1 + x];
+    let f4Up = lastLine ? lastLine[x] : 0;
+    let f4Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
+    let f4UpLeft = x > xBiggerThan && lastLine ? lastLine[x - xComparison] : 0;
+    let f4Add = paethPredictor(f4Left, f4Up, f4UpLeft);
+    unfilteredLine[x] = rawByte + f4Add;
+  }
+};
+ 
+Filter.prototype._reverseFilterLine = function (rawData) {
+  let filter = rawData[0];
+  let unfilteredLine;
+  let currentImage = this._images[this._imageIndex];
+  let byteWidth = currentImage.byteWidth;
+ 
+  if (filter === 0) {
+    unfilteredLine = rawData.slice(1, byteWidth + 1);
+  } else {
+    unfilteredLine = Buffer.alloc(byteWidth);
+ 
+    switch (filter) {
+      case 1:
+        this._unFilterType1(rawData, unfilteredLine, byteWidth);
+        break;
+      case 2:
+        this._unFilterType2(rawData, unfilteredLine, byteWidth);
+        break;
+      case 3:
+        this._unFilterType3(rawData, unfilteredLine, byteWidth);
+        break;
+      case 4:
+        this._unFilterType4(rawData, unfilteredLine, byteWidth);
+        break;
+      default:
+        throw new Error("Unrecognised filter type - " + filter);
+    }
+  }
+ 
+  this.write(unfilteredLine);
+ 
+  currentImage.lineIndex++;
+  if (currentImage.lineIndex >= currentImage.height) {
+    this._lastLine = null;
+    this._imageIndex++;
+    currentImage = this._images[this._imageIndex];
+  } else {
+    this._lastLine = unfilteredLine;
+  }
+ 
+  if (currentImage) {
+    // read, using the byte width that may be from the new current image
+    this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this));
+  } else {
+    this._lastLine = null;
+    this.complete();
+  }
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html b/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html new file mode 100644 index 0000000..c61afcf --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html @@ -0,0 +1,359 @@ + + + + + + Code coverage report for format-normaliser.js + + + + + + + + + +
+
+

All files format-normaliser.js

+
+ +
+ 98.21% + Statements + 55/56 +
+ + +
+ 95.24% + Branches + 20/21 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 97.87% + Lines + 46/47 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94  +  +  +131x +  +131x +4912x +1418436x +  +1418436x +  +  +  +1418436x +5673744x +  +1418436x +  +  +  +  +  +12x +12x +384x +12288x +  +12288x +6144x +2762x +  +6144x +  +  +  +  +2718x +  +12288x +5480x +21920x +  +  +12288x +  +  +  +  +  +106x +106x +106x +  +106x +3392x +108544x +434176x +  +  +  +108544x +  +  +  +  +1x +335x +335x +335x +335x +335x +335x +  +335x +  +335x +  +131x +  +204x +12x +  +  +204x +  +106x +66x +  +106x +  +  +335x +  + 
"use strict";
+ 
+function dePalette(indata, outdata, width, height, palette) {
+  let pxPos = 0;
+  // use values from palette
+  for (let y = 0; y < height; y++) {
+    for (let x = 0; x < width; x++) {
+      let color = palette[indata[pxPos]];
+ 
+      Iif (!color) {
+        throw new Error("index " + indata[pxPos] + " not in palette");
+      }
+ 
+      for (let i = 0; i < 4; i++) {
+        outdata[pxPos + i] = color[i];
+      }
+      pxPos += 4;
+    }
+  }
+}
+ 
+function replaceTransparentColor(indata, outdata, width, height, transColor) {
+  let pxPos = 0;
+  for (let y = 0; y < height; y++) {
+    for (let x = 0; x < width; x++) {
+      let makeTrans = false;
+ 
+      if (transColor.length === 1) {
+        if (transColor[0] === indata[pxPos]) {
+          makeTrans = true;
+        }
+      } else if (
+        transColor[0] === indata[pxPos] &&
+        transColor[1] === indata[pxPos + 1] &&
+        transColor[2] === indata[pxPos + 2]
+      ) {
+        makeTrans = true;
+      }
+      if (makeTrans) {
+        for (let i = 0; i < 4; i++) {
+          outdata[pxPos + i] = 0;
+        }
+      }
+      pxPos += 4;
+    }
+  }
+}
+ 
+function scaleDepth(indata, outdata, width, height, depth) {
+  let maxOutSample = 255;
+  let maxInSample = Math.pow(2, depth) - 1;
+  let pxPos = 0;
+ 
+  for (let y = 0; y < height; y++) {
+    for (let x = 0; x < width; x++) {
+      for (let i = 0; i < 4; i++) {
+        outdata[pxPos + i] = Math.floor(
+          (indata[pxPos + i] * maxOutSample) / maxInSample + 0.5
+        );
+      }
+      pxPos += 4;
+    }
+  }
+}
+ 
+module.exports = function (indata, imageData) {
+  let depth = imageData.depth;
+  let width = imageData.width;
+  let height = imageData.height;
+  let colorType = imageData.colorType;
+  let transColor = imageData.transColor;
+  let palette = imageData.palette;
+ 
+  let outdata = indata; // only different for 16 bits
+ 
+  if (colorType === 3) {
+    // paletted
+    dePalette(indata, outdata, width, height, palette);
+  } else {
+    if (transColor) {
+      replaceTransparentColor(indata, outdata, width, height, transColor);
+    }
+    // if it needs scaling
+    if (depth !== 8) {
+      // if we need to change the buffer size
+      if (depth === 16) {
+        outdata = Buffer.alloc(width * height * 4);
+      }
+      scaleDepth(indata, outdata, width, height, depth);
+    }
+  }
+  return outdata;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/index.html b/node_modules/pngjs/coverage/lcov-report/index.html new file mode 100644 index 0000000..51ecafd --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/index.html @@ -0,0 +1,426 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 82.72% + Statements + 1034/1250 +
+ + +
+ 67.59% + Branches + 317/469 +
+ + +
+ 90.26% + Functions + 139/154 +
+ + +
+ 82.53% + Lines + 992/1202 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
bitmapper.js +
+
94.37%134/14272.41%21/2989.47%17/1994.16%129/137
bitpacker.js +
+
11.36%10/886.12%3/4966.67%2/311.63%10/86
chunkstream.js +
+
90.11%82/9181.4%35/43100%10/1090.11%82/91
constants.js +
+
100%1/1100%0/0100%0/0100%1/1
crc.js +
+
100%26/26100%2/2100%5/5100%22/22
filter-pack.js +
+
95.83%92/9681.82%36/44100%11/1195.24%80/84
filter-parse-async.js +
+
100%12/12100%0/0100%3/3100%12/12
filter-parse-sync.js +
+
100%10/10100%0/0100%3/3100%10/10
filter-parse.js +
+
98.96%95/9697.14%34/35100%8/898.9%90/91
format-normaliser.js +
+
98.21%55/5695.24%20/21100%4/497.87%46/47
interlace.js +
+
100%32/32100%8/8100%3/3100%29/29
packer-async.js +
+
100%24/2475%3/4100%4/4100%24/24
packer-sync.js +
+
25%6/248.33%1/120%0/125%6/24
packer.js +
+
94.74%54/5767.86%19/28100%9/994.74%54/57
paeth-predictor.js +
+
100%10/10100%6/6100%1/1100%10/10
parser-async.js +
+
88.75%71/8072.73%16/2284.62%11/1388.75%71/80
parser-sync.js +
+
93.33%42/4578.57%11/14100%8/893.33%42/45
parser.js +
+
90.57%144/15985.45%47/55100%20/2090.32%140/155
png-sync.js +
+
83.33%5/6100%2/250%1/283.33%5/6
png.js +
+
54.17%52/9641.18%14/3456.25%9/1656.52%52/92
sync-inflate.js +
+
75.31%61/8162%31/5087.5%7/875.31%61/81
sync-reader.js +
+
88.89%16/1872.73%8/11100%3/388.89%16/18
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/interlace.js.html b/node_modules/pngjs/coverage/lcov-report/interlace.js.html new file mode 100644 index 0000000..d67b087 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/interlace.js.html @@ -0,0 +1,365 @@ + + + + + + Code coverage report for interlace.js + + + + + + + + + +
+
+

All files interlace.js

+
+ +
+ 100% + Statements + 32/32 +
+ + +
+ 100% + Branches + 8/8 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 100% + Lines + 29/29 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +144x +144x +144x +144x +144x +144x +1008x +1008x +1008x +1008x +1556x +672x +  +884x +  +  +1008x +1360x +552x +  +808x +  +  +1008x +952x +  +  +144x +  +  +1x +72x +324850x +  +324850x +  +324850x +  +324850x +  +324850x +  +  + 
"use strict";
+ 
+// Adam 7
+//   0 1 2 3 4 5 6 7
+// 0 x 6 4 6 x 6 4 6
+// 1 7 7 7 7 7 7 7 7
+// 2 5 6 5 6 5 6 5 6
+// 3 7 7 7 7 7 7 7 7
+// 4 3 6 4 6 3 6 4 6
+// 5 7 7 7 7 7 7 7 7
+// 6 5 6 5 6 5 6 5 6
+// 7 7 7 7 7 7 7 7 7
+ 
+let imagePasses = [
+  {
+    // pass 1 - 1px
+    x: [0],
+    y: [0],
+  },
+  {
+    // pass 2 - 1px
+    x: [4],
+    y: [0],
+  },
+  {
+    // pass 3 - 2px
+    x: [0, 4],
+    y: [4],
+  },
+  {
+    // pass 4 - 4px
+    x: [2, 6],
+    y: [0, 4],
+  },
+  {
+    // pass 5 - 8px
+    x: [0, 2, 4, 6],
+    y: [2, 6],
+  },
+  {
+    // pass 6 - 16px
+    x: [1, 3, 5, 7],
+    y: [0, 2, 4, 6],
+  },
+  {
+    // pass 7 - 32px
+    x: [0, 1, 2, 3, 4, 5, 6, 7],
+    y: [1, 3, 5, 7],
+  },
+];
+ 
+exports.getImagePasses = function (width, height) {
+  let images = [];
+  let xLeftOver = width % 8;
+  let yLeftOver = height % 8;
+  let xRepeats = (width - xLeftOver) / 8;
+  let yRepeats = (height - yLeftOver) / 8;
+  for (let i = 0; i < imagePasses.length; i++) {
+    let pass = imagePasses[i];
+    let passWidth = xRepeats * pass.x.length;
+    let passHeight = yRepeats * pass.y.length;
+    for (let j = 0; j < pass.x.length; j++) {
+      if (pass.x[j] < xLeftOver) {
+        passWidth++;
+      } else {
+        break;
+      }
+    }
+    for (let j = 0; j < pass.y.length; j++) {
+      if (pass.y[j] < yLeftOver) {
+        passHeight++;
+      } else {
+        break;
+      }
+    }
+    if (passWidth > 0 && passHeight > 0) {
+      images.push({ width: passWidth, height: passHeight, index: i });
+    }
+  }
+  return images;
+};
+ 
+exports.getInterlaceIterator = function (width) {
+  return function (x, y, pass) {
+    let outerXLeftOver = x % imagePasses[pass].x.length;
+    let outerX =
+      ((x - outerXLeftOver) / imagePasses[pass].x.length) * 8 +
+      imagePasses[pass].x[outerXLeftOver];
+    let outerYLeftOver = y % imagePasses[pass].y.length;
+    let outerY =
+      ((y - outerYLeftOver) / imagePasses[pass].y.length) * 8 +
+      imagePasses[pass].y[outerYLeftOver];
+    return outerX * 4 + outerY * width * 4;
+  };
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/packer-async.js.html b/node_modules/pngjs/coverage/lcov-report/packer-async.js.html new file mode 100644 index 0000000..55365c7 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/packer-async.js.html @@ -0,0 +1,230 @@ + + + + + + Code coverage report for packer-async.js + + + + + + + + + +
+
+

All files packer-async.js

+
+ +
+ 100% + Statements + 24/24 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 24/24 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51  +  +1x +1x +1x +1x +  +1x +353x +  +353x +  +353x +353x +  +353x +  +1x +  +1x +  +325x +325x +  +325x +290x +  +  +325x +  +  +325x +  +325x +  +  +652x +  +  +  +325x +  +  +325x +325x +  +  +  +325x +  + 
"use strict";
+ 
+let util = require("util");
+let Stream = require("stream");
+let constants = require("./constants");
+let Packer = require("./packer");
+ 
+let PackerAsync = (module.exports = function (opt) {
+  Stream.call(this);
+ 
+  let options = opt || {};
+ 
+  this._packer = new Packer(options);
+  this._deflate = this._packer.createDeflate();
+ 
+  this.readable = true;
+});
+util.inherits(PackerAsync, Stream);
+ 
+PackerAsync.prototype.pack = function (data, width, height, gamma) {
+  // Signature
+  this.emit("data", Buffer.from(constants.PNG_SIGNATURE));
+  this.emit("data", this._packer.packIHDR(width, height));
+ 
+  if (gamma) {
+    this.emit("data", this._packer.packGAMA(gamma));
+  }
+ 
+  let filteredData = this._packer.filterData(data, width, height);
+ 
+  // compress it
+  this._deflate.on("error", this.emit.bind(this, "error"));
+ 
+  this._deflate.on(
+    "data",
+    function (compressedData) {
+      this.emit("data", this._packer.packIDAT(compressedData));
+    }.bind(this)
+  );
+ 
+  this._deflate.on(
+    "end",
+    function () {
+      this.emit("data", this._packer.packIEND());
+      this.emit("end");
+    }.bind(this)
+  );
+ 
+  this._deflate.end(filteredData);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html b/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html new file mode 100644 index 0000000..86283b5 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html @@ -0,0 +1,248 @@ + + + + + + Code coverage report for packer-sync.js + + + + + + + + + +
+
+

All files packer-sync.js

+
+ +
+ 25% + Statements + 6/24 +
+ + +
+ 8.33% + Branches + 1/12 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 25% + Lines + 6/24 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57  +  +1x +1x +1x +  +  +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
"use strict";
+ 
+let hasSyncZlib = true;
+let zlib = require("zlib");
+Iif (!zlib.deflateSync) {
+  hasSyncZlib = false;
+}
+let constants = require("./constants");
+let Packer = require("./packer");
+ 
+module.exports = function (metaData, opt) {
+  if (!hasSyncZlib) {
+    throw new Error(
+      "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0"
+    );
+  }
+ 
+  let options = opt || {};
+ 
+  let packer = new Packer(options);
+ 
+  let chunks = [];
+ 
+  // Signature
+  chunks.push(Buffer.from(constants.PNG_SIGNATURE));
+ 
+  // Header
+  chunks.push(packer.packIHDR(metaData.width, metaData.height));
+ 
+  if (metaData.gamma) {
+    chunks.push(packer.packGAMA(metaData.gamma));
+  }
+ 
+  let filteredData = packer.filterData(
+    metaData.data,
+    metaData.width,
+    metaData.height
+  );
+ 
+  // compress it
+  let compressedData = zlib.deflateSync(
+    filteredData,
+    packer.getDeflateOptions()
+  );
+  filteredData = null;
+ 
+  if (!compressedData || !compressedData.length) {
+    throw new Error("bad png - invalid compressed data response");
+  }
+  chunks.push(packer.packIDAT(compressedData));
+ 
+  // End
+  chunks.push(packer.packIEND());
+ 
+  return Buffer.concat(chunks);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/packer.js.html b/node_modules/pngjs/coverage/lcov-report/packer.js.html new file mode 100644 index 0000000..606e193 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/packer.js.html @@ -0,0 +1,467 @@ + + + + + + Code coverage report for packer.js + + + + + + + + + +
+
+

All files packer.js

+
+ +
+ 94.74% + Statements + 54/57 +
+ + +
+ 67.86% + Branches + 19/28 +
+ + +
+ 100% + Functions + 9/9 +
+ + +
+ 94.74% + Lines + 54/57 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130  +  +1x +1x +1x +1x +1x +  +1x +353x +  +353x +353x +  +353x +  +353x +  +353x +353x +  +353x +  +  +  +353x +  +  +  +  +353x +  +  +  +  +  +  +  +  +  +  +  +353x +  +  +  +  +  +  +  +  +  +  +  +  +  +353x +  +  +  +  +  +  +1x +353x +  +  +  +  +  +  +1x +353x +  +  +1x +  +325x +  +  +325x +325x +325x +  +  +1x +1592x +1592x +  +1592x +1592x +  +1592x +1267x +  +  +1592x +  +  +  +1592x +  +  +1x +290x +290x +290x +  +  +1x +325x +325x +325x +325x +325x +325x +325x +325x +  +325x +  +  +1x +652x +  +  +1x +325x +  + 
"use strict";
+ 
+let constants = require("./constants");
+let CrcStream = require("./crc");
+let bitPacker = require("./bitpacker");
+let filter = require("./filter-pack");
+let zlib = require("zlib");
+ 
+let Packer = (module.exports = function (options) {
+  this._options = options;
+ 
+  options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
+  options.deflateLevel =
+    options.deflateLevel != null ? options.deflateLevel : 9;
+  options.deflateStrategy =
+    options.deflateStrategy != null ? options.deflateStrategy : 3;
+  options.inputHasAlpha =
+    options.inputHasAlpha != null ? options.inputHasAlpha : true;
+  options.deflateFactory = options.deflateFactory || zlib.createDeflate;
+  options.bitDepth = options.bitDepth || 8;
+  // This is outputColorType
+  options.colorType =
+    typeof options.colorType === "number"
+      ? options.colorType
+      : constants.COLORTYPE_COLOR_ALPHA;
+  options.inputColorType =
+    typeof options.inputColorType === "number"
+      ? options.inputColorType
+      : constants.COLORTYPE_COLOR_ALPHA;
+ 
+  Iif (
+    [
+      constants.COLORTYPE_GRAYSCALE,
+      constants.COLORTYPE_COLOR,
+      constants.COLORTYPE_COLOR_ALPHA,
+      constants.COLORTYPE_ALPHA,
+    ].indexOf(options.colorType) === -1
+  ) {
+    throw new Error(
+      "option color type:" + options.colorType + " is not supported at present"
+    );
+  }
+  Iif (
+    [
+      constants.COLORTYPE_GRAYSCALE,
+      constants.COLORTYPE_COLOR,
+      constants.COLORTYPE_COLOR_ALPHA,
+      constants.COLORTYPE_ALPHA,
+    ].indexOf(options.inputColorType) === -1
+  ) {
+    throw new Error(
+      "option input color type:" +
+        options.inputColorType +
+        " is not supported at present"
+    );
+  }
+  Iif (options.bitDepth !== 8 && options.bitDepth !== 16) {
+    throw new Error(
+      "option bit depth:" + options.bitDepth + " is not supported at present"
+    );
+  }
+});
+ 
+Packer.prototype.getDeflateOptions = function () {
+  return {
+    chunkSize: this._options.deflateChunkSize,
+    level: this._options.deflateLevel,
+    strategy: this._options.deflateStrategy,
+  };
+};
+ 
+Packer.prototype.createDeflate = function () {
+  return this._options.deflateFactory(this.getDeflateOptions());
+};
+ 
+Packer.prototype.filterData = function (data, width, height) {
+  // convert to correct format for filtering (e.g. right bpp and bit depth)
+  let packedData = bitPacker(data, width, height, this._options);
+ 
+  // filter pixel data
+  let bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType];
+  let filteredData = filter(packedData, width, height, this._options, bpp);
+  return filteredData;
+};
+ 
+Packer.prototype._packChunk = function (type, data) {
+  let len = data ? data.length : 0;
+  let buf = Buffer.alloc(len + 12);
+ 
+  buf.writeUInt32BE(len, 0);
+  buf.writeUInt32BE(type, 4);
+ 
+  if (data) {
+    data.copy(buf, 8);
+  }
+ 
+  buf.writeInt32BE(
+    CrcStream.crc32(buf.slice(4, buf.length - 4)),
+    buf.length - 4
+  );
+  return buf;
+};
+ 
+Packer.prototype.packGAMA = function (gamma) {
+  let buf = Buffer.alloc(4);
+  buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0);
+  return this._packChunk(constants.TYPE_gAMA, buf);
+};
+ 
+Packer.prototype.packIHDR = function (width, height) {
+  let buf = Buffer.alloc(13);
+  buf.writeUInt32BE(width, 0);
+  buf.writeUInt32BE(height, 4);
+  buf[8] = this._options.bitDepth; // Bit depth
+  buf[9] = this._options.colorType; // colorType
+  buf[10] = 0; // compression
+  buf[11] = 0; // filter
+  buf[12] = 0; // interlace
+ 
+  return this._packChunk(constants.TYPE_IHDR, buf);
+};
+ 
+Packer.prototype.packIDAT = function (data) {
+  return this._packChunk(constants.TYPE_IDAT, data);
+};
+ 
+Packer.prototype.packIEND = function () {
+  return this._packChunk(constants.TYPE_IEND, null);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html b/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html new file mode 100644 index 0000000..6385999 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html @@ -0,0 +1,128 @@ + + + + + + Code coverage report for paeth-predictor.js + + + + + + + + + +
+
+

All files paeth-predictor.js

+
+ +
+ 100% + Statements + 10/10 +
+ + +
+ 100% + Branches + 6/6 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 10/10 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17  +  +1x +5808408x +5808408x +5808408x +5808408x +  +5808408x +5156742x +  +651666x +539893x +  +111773x +  + 
"use strict";
+ 
+module.exports = function paethPredictor(left, above, upLeft) {
+  let paeth = left + above - upLeft;
+  let pLeft = Math.abs(paeth - left);
+  let pAbove = Math.abs(paeth - above);
+  let pUpLeft = Math.abs(paeth - upLeft);
+ 
+  if (pLeft <= pAbove && pLeft <= pUpLeft) {
+    return left;
+  }
+  if (pAbove <= pUpLeft) {
+    return above;
+  }
+  return upLeft;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/parser-async.js.html b/node_modules/pngjs/coverage/lcov-report/parser-async.js.html new file mode 100644 index 0000000..77074ff --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/parser-async.js.html @@ -0,0 +1,575 @@ + + + + + + Code coverage report for parser-async.js + + + + + + + + + +
+
+

All files parser-async.js

+
+ +
+ 88.75% + Statements + 71/80 +
+ + +
+ 72.73% + Branches + 16/22 +
+ + +
+ 84.62% + Functions + 11/13 +
+ + +
+ 88.75% + Lines + 71/80 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166  +  +1x +1x +1x +1x +1x +1x +1x +  +1x +353x +  +353x +  +  +  +  +  +  +  +  +  +  +  +353x +353x +  +353x +  +1x +  +1x +14x +  +14x +  +14x +  +14x +1x +  +  +14x +2x +  +  +  +2x +  +  +14x +  +  +1x +741x +174x +36x +  +36x +36x +  +36x +  +  +138x +  +  +  +  +  +138x +138x +  +138x +138x +  +138x +138x +  +  +  +  +  +  +138x +  +138x +138x +487x +  +  +  +487x +  +  +  +487x +  +487x +  +  +138x +  +  +741x +  +  +1x +176x +176x +  +176x +  +  +1x +7x +  +  +1x +77x +  +  +1x +15x +  +  +1x +  +  +174x +  +  +1x +173x +  +  +  +173x +1x +  +  +172x +  +  +  +1x +173x +  +  +  +  +  +173x +173x +  +173x +173x +  +  +  +  +  +173x +  + 
"use strict";
+ 
+let util = require("util");
+let zlib = require("zlib");
+let ChunkStream = require("./chunkstream");
+let FilterAsync = require("./filter-parse-async");
+let Parser = require("./parser");
+let bitmapper = require("./bitmapper");
+let formatNormaliser = require("./format-normaliser");
+ 
+let ParserAsync = (module.exports = function (options) {
+  ChunkStream.call(this);
+ 
+  this._parser = new Parser(options, {
+    read: this.read.bind(this),
+    error: this._handleError.bind(this),
+    metadata: this._handleMetaData.bind(this),
+    gamma: this.emit.bind(this, "gamma"),
+    palette: this._handlePalette.bind(this),
+    transColor: this._handleTransColor.bind(this),
+    finished: this._finished.bind(this),
+    inflateData: this._inflateData.bind(this),
+    simpleTransparency: this._simpleTransparency.bind(this),
+    headersFinished: this._headersFinished.bind(this),
+  });
+  this._options = options;
+  this.writable = true;
+ 
+  this._parser.start();
+});
+util.inherits(ParserAsync, ChunkStream);
+ 
+ParserAsync.prototype._handleError = function (err) {
+  this.emit("error", err);
+ 
+  this.writable = false;
+ 
+  this.destroy();
+ 
+  if (this._inflate && this._inflate.destroy) {
+    this._inflate.destroy();
+  }
+ 
+  if (this._filter) {
+    this._filter.destroy();
+    // For backward compatibility with Node 7 and below.
+    // Suppress errors due to _inflate calling write() even after
+    // it's destroy()'ed.
+    this._filter.on("error", function () {});
+  }
+ 
+  this.errord = true;
+};
+ 
+ParserAsync.prototype._inflateData = function (data) {
+  if (!this._inflate) {
+    if (this._bitmapInfo.interlace) {
+      this._inflate = zlib.createInflate();
+ 
+      this._inflate.on("error", this.emit.bind(this, "error"));
+      this._filter.on("complete", this._complete.bind(this));
+ 
+      this._inflate.pipe(this._filter);
+    } else {
+      let rowSize =
+        ((this._bitmapInfo.width *
+          this._bitmapInfo.bpp *
+          this._bitmapInfo.depth +
+          7) >>
+          3) +
+        1;
+      let imageSize = rowSize * this._bitmapInfo.height;
+      let chunkSize = Math.max(imageSize, zlib.Z_MIN_CHUNK);
+ 
+      this._inflate = zlib.createInflate({ chunkSize: chunkSize });
+      let leftToInflate = imageSize;
+ 
+      let emitError = this.emit.bind(this, "error");
+      this._inflate.on("error", function (err) {
+        if (!leftToInflate) {
+          return;
+        }
+ 
+        emitError(err);
+      });
+      this._filter.on("complete", this._complete.bind(this));
+ 
+      let filterWrite = this._filter.write.bind(this._filter);
+      this._inflate.on("data", function (chunk) {
+        Iif (!leftToInflate) {
+          return;
+        }
+ 
+        Iif (chunk.length > leftToInflate) {
+          chunk = chunk.slice(0, leftToInflate);
+        }
+ 
+        leftToInflate -= chunk.length;
+ 
+        filterWrite(chunk);
+      });
+ 
+      this._inflate.on("end", this._filter.end.bind(this._filter));
+    }
+  }
+  this._inflate.write(data);
+};
+ 
+ParserAsync.prototype._handleMetaData = function (metaData) {
+  this._metaData = metaData;
+  this._bitmapInfo = Object.create(metaData);
+ 
+  this._filter = new FilterAsync(this._bitmapInfo);
+};
+ 
+ParserAsync.prototype._handleTransColor = function (transColor) {
+  this._bitmapInfo.transColor = transColor;
+};
+ 
+ParserAsync.prototype._handlePalette = function (palette) {
+  this._bitmapInfo.palette = palette;
+};
+ 
+ParserAsync.prototype._simpleTransparency = function () {
+  this._metaData.alpha = true;
+};
+ 
+ParserAsync.prototype._headersFinished = function () {
+  // Up until this point, we don't know if we have a tRNS chunk (alpha)
+  // so we can't emit metadata any earlier
+  this.emit("metadata", this._metaData);
+};
+ 
+ParserAsync.prototype._finished = function () {
+  Iif (this.errord) {
+    return;
+  }
+ 
+  if (!this._inflate) {
+    this.emit("error", "No Inflate block");
+  } else {
+    // no more data to inflate
+    this._inflate.end();
+  }
+};
+ 
+ParserAsync.prototype._complete = function (filteredData) {
+  Iif (this.errord) {
+    return;
+  }
+ 
+  let normalisedBitmapData;
+ 
+  try {
+    let bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo);
+ 
+    normalisedBitmapData = formatNormaliser(bitmapData, this._bitmapInfo);
+    bitmapData = null;
+  } catch (ex) {
+    this._handleError(ex);
+    return;
+  }
+ 
+  this.emit("parsed", normalisedBitmapData);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html b/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html new file mode 100644 index 0000000..6ced1a9 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html @@ -0,0 +1,404 @@ + + + + + + Code coverage report for parser-sync.js + + + + + + + + + +
+
+

All files parser-sync.js

+
+ +
+ 93.33% + Statements + 42/45 +
+ + +
+ 78.57% + Branches + 11/14 +
+ + +
+ 100% + Functions + 8/8 +
+ + +
+ 93.33% + Lines + 42/45 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109  +  +1x +1x +1x +1x +  +  +1x +1x +1x +1x +1x +  +1x +176x +  +  +  +  +  +  +  +13x +  +  +  +  +165x +  +  +  +5x +  +  +  +73x +  +  +  +12x +  +  +  +  +147x +  +  +176x +  +492x +  +  +176x +  +176x +  +  +  +  +  +  +  +  +  +  +176x +176x +  +176x +13x +  +  +  +163x +163x +  +  +163x +36x +  +  +127x +127x +127x +  +  +  +  +162x +  +162x +  +  +  +162x +162x +  +162x +162x +  +162x +  +162x +162x +  +162x +  + 
"use strict";
+ 
+let hasSyncZlib = true;
+let zlib = require("zlib");
+let inflateSync = require("./sync-inflate");
+Iif (!zlib.deflateSync) {
+  hasSyncZlib = false;
+}
+let SyncReader = require("./sync-reader");
+let FilterSync = require("./filter-parse-sync");
+let Parser = require("./parser");
+let bitmapper = require("./bitmapper");
+let formatNormaliser = require("./format-normaliser");
+ 
+module.exports = function (buffer, options) {
+  Iif (!hasSyncZlib) {
+    throw new Error(
+      "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0"
+    );
+  }
+ 
+  let err;
+  function handleError(_err_) {
+    err = _err_;
+  }
+ 
+  let metaData;
+  function handleMetaData(_metaData_) {
+    metaData = _metaData_;
+  }
+ 
+  function handleTransColor(transColor) {
+    metaData.transColor = transColor;
+  }
+ 
+  function handlePalette(palette) {
+    metaData.palette = palette;
+  }
+ 
+  function handleSimpleTransparency() {
+    metaData.alpha = true;
+  }
+ 
+  let gamma;
+  function handleGamma(_gamma_) {
+    gamma = _gamma_;
+  }
+ 
+  let inflateDataList = [];
+  function handleInflateData(inflatedData) {
+    inflateDataList.push(inflatedData);
+  }
+ 
+  let reader = new SyncReader(buffer);
+ 
+  let parser = new Parser(options, {
+    read: reader.read.bind(reader),
+    error: handleError,
+    metadata: handleMetaData,
+    gamma: handleGamma,
+    palette: handlePalette,
+    transColor: handleTransColor,
+    inflateData: handleInflateData,
+    simpleTransparency: handleSimpleTransparency,
+  });
+ 
+  parser.start();
+  reader.process();
+ 
+  if (err) {
+    throw err;
+  }
+ 
+  //join together the inflate datas
+  let inflateData = Buffer.concat(inflateDataList);
+  inflateDataList.length = 0;
+ 
+  let inflatedData;
+  if (metaData.interlace) {
+    inflatedData = zlib.inflateSync(inflateData);
+  } else {
+    let rowSize =
+      ((metaData.width * metaData.bpp * metaData.depth + 7) >> 3) + 1;
+    let imageSize = rowSize * metaData.height;
+    inflatedData = inflateSync(inflateData, {
+      chunkSize: imageSize,
+      maxLength: imageSize,
+    });
+  }
+  inflateData = null;
+ 
+  Iif (!inflatedData || !inflatedData.length) {
+    throw new Error("bad png - invalid inflate data response");
+  }
+ 
+  let unfilteredData = FilterSync.process(inflatedData, metaData);
+  inflateData = null;
+ 
+  let bitmapData = bitmapper.dataToBitMap(unfilteredData, metaData);
+  unfilteredData = null;
+ 
+  let normalisedBitmapData = formatNormaliser(bitmapData, metaData);
+ 
+  metaData.data = normalisedBitmapData;
+  metaData.gamma = gamma || 0;
+ 
+  return metaData;
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/parser.js.html b/node_modules/pngjs/coverage/lcov-report/parser.js.html new file mode 100644 index 0000000..efc9504 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/parser.js.html @@ -0,0 +1,950 @@ + + + + + + Code coverage report for parser.js + + + + + + + + + +
+
+

All files parser.js

+
+ +
+ 90.57% + Statements + 144/159 +
+ + +
+ 85.45% + Branches + 47/55 +
+ + +
+ 100% + Functions + 20/20 +
+ + +
+ 90.32% + Lines + 140/155 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291  +  +1x +1x +  +1x +529x +529x +  +529x +529x +529x +  +  +529x +529x +  +529x +529x +529x +529x +529x +529x +529x +  +529x +529x +529x +529x +529x +529x +529x +529x +529x +529x +529x +  +  +1x +529x +  +  +1x +365x +  +365x +2867x +13x +13x +  +  +352x +  +  +1x +  +2461x +  +  +2461x +2461x +2461x +9844x +  +  +  +  +  +2461x +  +  +  +2461x +  +  +  +  +2461x +2461x +  +2461x +2205x +  +  +256x +  +  +  +  +256x +  +  +1x +256x +  +  +1x +2195x +  +  +1x +2195x +2195x +  +  +2195x +4x +4x +  +  +2191x +1855x +  +  +  +1x +351x +  +1x +351x +  +351x +351x +351x +351x +351x +351x +351x +  +  +  +  +  +  +351x +  +  +  +  +  +  +6x +6x +  +345x +4x +4x +  +341x +  +  +  +341x +  +  +  +341x +  +  +  +  +341x +  +341x +  +341x +  +341x +  +  +  +  +  +  +  +  +  +  +  +341x +  +  +1x +135x +  +1x +135x +  +135x +  +  +135x +7350x +  +  +135x +  +135x +  +  +1x +27x +27x +  +1x +27x +  +  +27x +15x +  +  +  +15x +  +  +  +15x +529x +  +15x +  +  +  +  +27x +  +6x +  +27x +6x +  +  +  +  +  +  +27x +  +  +1x +296x +  +1x +296x +296x +  +296x +  +  +1x +1233x +337x +337x +  +1233x +  +1x +1233x +  +1233x +  +  +  +  +  +  +1233x +1233x +  +1233x +173x +  +1060x +  +  +  +1x +336x +  +1x +336x +  +336x +336x +  +336x +173x +  +  + 
"use strict";
+ 
+let constants = require("./constants");
+let CrcCalculator = require("./crc");
+ 
+let Parser = (module.exports = function (options, dependencies) {
+  this._options = options;
+  options.checkCRC = options.checkCRC !== false;
+ 
+  this._hasIHDR = false;
+  this._hasIEND = false;
+  this._emittedHeadersFinished = false;
+ 
+  // input flags/metadata
+  this._palette = [];
+  this._colorType = 0;
+ 
+  this._chunks = {};
+  this._chunks[constants.TYPE_IHDR] = this._handleIHDR.bind(this);
+  this._chunks[constants.TYPE_IEND] = this._handleIEND.bind(this);
+  this._chunks[constants.TYPE_IDAT] = this._handleIDAT.bind(this);
+  this._chunks[constants.TYPE_PLTE] = this._handlePLTE.bind(this);
+  this._chunks[constants.TYPE_tRNS] = this._handleTRNS.bind(this);
+  this._chunks[constants.TYPE_gAMA] = this._handleGAMA.bind(this);
+ 
+  this.read = dependencies.read;
+  this.error = dependencies.error;
+  this.metadata = dependencies.metadata;
+  this.gamma = dependencies.gamma;
+  this.transColor = dependencies.transColor;
+  this.palette = dependencies.palette;
+  this.parsed = dependencies.parsed;
+  this.inflateData = dependencies.inflateData;
+  this.finished = dependencies.finished;
+  this.simpleTransparency = dependencies.simpleTransparency;
+  this.headersFinished = dependencies.headersFinished || function () {};
+});
+ 
+Parser.prototype.start = function () {
+  this.read(constants.PNG_SIGNATURE.length, this._parseSignature.bind(this));
+};
+ 
+Parser.prototype._parseSignature = function (data) {
+  let signature = constants.PNG_SIGNATURE;
+ 
+  for (let i = 0; i < signature.length; i++) {
+    if (data[i] !== signature[i]) {
+      this.error(new Error("Invalid file signature"));
+      return;
+    }
+  }
+  this.read(8, this._parseChunkBegin.bind(this));
+};
+ 
+Parser.prototype._parseChunkBegin = function (data) {
+  // chunk content length
+  let length = data.readUInt32BE(0);
+ 
+  // chunk type
+  let type = data.readUInt32BE(4);
+  let name = "";
+  for (let i = 4; i < 8; i++) {
+    name += String.fromCharCode(data[i]);
+  }
+ 
+  //console.log('chunk ', name, length);
+ 
+  // chunk flags
+  let ancillary = Boolean(data[4] & 0x20); // or critical
+  //    priv = Boolean(data[5] & 0x20), // or public
+  //    safeToCopy = Boolean(data[7] & 0x20); // or unsafe
+ 
+  Iif (!this._hasIHDR && type !== constants.TYPE_IHDR) {
+    this.error(new Error("Expected IHDR on beggining"));
+    return;
+  }
+ 
+  this._crc = new CrcCalculator();
+  this._crc.write(Buffer.from(name));
+ 
+  if (this._chunks[type]) {
+    return this._chunks[type](length);
+  }
+ 
+  Iif (!ancillary) {
+    this.error(new Error("Unsupported critical chunk type " + name));
+    return;
+  }
+ 
+  this.read(length + 4, this._skipChunk.bind(this));
+};
+ 
+Parser.prototype._skipChunk = function (/*data*/) {
+  this.read(8, this._parseChunkBegin.bind(this));
+};
+ 
+Parser.prototype._handleChunkEnd = function () {
+  this.read(4, this._parseChunkEnd.bind(this));
+};
+ 
+Parser.prototype._parseChunkEnd = function (data) {
+  let fileCrc = data.readInt32BE(0);
+  let calcCrc = this._crc.crc32();
+ 
+  // check CRC
+  if (this._options.checkCRC && calcCrc !== fileCrc) {
+    this.error(new Error("Crc error - " + fileCrc + " - " + calcCrc));
+    return;
+  }
+ 
+  if (!this._hasIEND) {
+    this.read(8, this._parseChunkBegin.bind(this));
+  }
+};
+ 
+Parser.prototype._handleIHDR = function (length) {
+  this.read(length, this._parseIHDR.bind(this));
+};
+Parser.prototype._parseIHDR = function (data) {
+  this._crc.write(data);
+ 
+  let width = data.readUInt32BE(0);
+  let height = data.readUInt32BE(4);
+  let depth = data[8];
+  let colorType = data[9]; // bits: 1 palette, 2 color, 4 alpha
+  let compr = data[10];
+  let filter = data[11];
+  let interlace = data[12];
+ 
+  // console.log('    width', width, 'height', height,
+  //     'depth', depth, 'colorType', colorType,
+  //     'compr', compr, 'filter', filter, 'interlace', interlace
+  // );
+ 
+  if (
+    depth !== 8 &&
+    depth !== 4 &&
+    depth !== 2 &&
+    depth !== 1 &&
+    depth !== 16
+  ) {
+    this.error(new Error("Unsupported bit depth " + depth));
+    return;
+  }
+  if (!(colorType in constants.COLORTYPE_TO_BPP_MAP)) {
+    this.error(new Error("Unsupported color type"));
+    return;
+  }
+  Iif (compr !== 0) {
+    this.error(new Error("Unsupported compression method"));
+    return;
+  }
+  Iif (filter !== 0) {
+    this.error(new Error("Unsupported filter method"));
+    return;
+  }
+  Iif (interlace !== 0 && interlace !== 1) {
+    this.error(new Error("Unsupported interlace method"));
+    return;
+  }
+ 
+  this._colorType = colorType;
+ 
+  let bpp = constants.COLORTYPE_TO_BPP_MAP[this._colorType];
+ 
+  this._hasIHDR = true;
+ 
+  this.metadata({
+    width: width,
+    height: height,
+    depth: depth,
+    interlace: Boolean(interlace),
+    palette: Boolean(colorType & constants.COLORTYPE_PALETTE),
+    color: Boolean(colorType & constants.COLORTYPE_COLOR),
+    alpha: Boolean(colorType & constants.COLORTYPE_ALPHA),
+    bpp: bpp,
+    colorType: colorType,
+  });
+ 
+  this._handleChunkEnd();
+};
+ 
+Parser.prototype._handlePLTE = function (length) {
+  this.read(length, this._parsePLTE.bind(this));
+};
+Parser.prototype._parsePLTE = function (data) {
+  this._crc.write(data);
+ 
+  let entries = Math.floor(data.length / 3);
+  // console.log('Palette:', entries);
+ 
+  for (let i = 0; i < entries; i++) {
+    this._palette.push([data[i * 3], data[i * 3 + 1], data[i * 3 + 2], 0xff]);
+  }
+ 
+  this.palette(this._palette);
+ 
+  this._handleChunkEnd();
+};
+ 
+Parser.prototype._handleTRNS = function (length) {
+  this.simpleTransparency();
+  this.read(length, this._parseTRNS.bind(this));
+};
+Parser.prototype._parseTRNS = function (data) {
+  this._crc.write(data);
+ 
+  // palette
+  if (this._colorType === constants.COLORTYPE_PALETTE_COLOR) {
+    Iif (this._palette.length === 0) {
+      this.error(new Error("Transparency chunk must be after palette"));
+      return;
+    }
+    Iif (data.length > this._palette.length) {
+      this.error(new Error("More transparent colors than palette size"));
+      return;
+    }
+    for (let i = 0; i < data.length; i++) {
+      this._palette[i][3] = data[i];
+    }
+    this.palette(this._palette);
+  }
+ 
+  // for colorType 0 (grayscale) and 2 (rgb)
+  // there might be one gray/color defined as transparent
+  if (this._colorType === constants.COLORTYPE_GRAYSCALE) {
+    // grey, 2 bytes
+    this.transColor([data.readUInt16BE(0)]);
+  }
+  if (this._colorType === constants.COLORTYPE_COLOR) {
+    this.transColor([
+      data.readUInt16BE(0),
+      data.readUInt16BE(2),
+      data.readUInt16BE(4),
+    ]);
+  }
+ 
+  this._handleChunkEnd();
+};
+ 
+Parser.prototype._handleGAMA = function (length) {
+  this.read(length, this._parseGAMA.bind(this));
+};
+Parser.prototype._parseGAMA = function (data) {
+  this._crc.write(data);
+  this.gamma(data.readUInt32BE(0) / constants.GAMMA_DIVISION);
+ 
+  this._handleChunkEnd();
+};
+ 
+Parser.prototype._handleIDAT = function (length) {
+  if (!this._emittedHeadersFinished) {
+    this._emittedHeadersFinished = true;
+    this.headersFinished();
+  }
+  this.read(-length, this._parseIDAT.bind(this, length));
+};
+Parser.prototype._parseIDAT = function (length, data) {
+  this._crc.write(data);
+ 
+  Iif (
+    this._colorType === constants.COLORTYPE_PALETTE_COLOR &&
+    this._palette.length === 0
+  ) {
+    throw new Error("Expected palette not found");
+  }
+ 
+  this.inflateData(data);
+  let leftOverLength = length - data.length;
+ 
+  if (leftOverLength > 0) {
+    this._handleIDAT(leftOverLength);
+  } else {
+    this._handleChunkEnd();
+  }
+};
+ 
+Parser.prototype._handleIEND = function (length) {
+  this.read(length, this._parseIEND.bind(this));
+};
+Parser.prototype._parseIEND = function (data) {
+  this._crc.write(data);
+ 
+  this._hasIEND = true;
+  this._handleChunkEnd();
+ 
+  if (this.finished) {
+    this.finished();
+  }
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/png-sync.js.html b/node_modules/pngjs/coverage/lcov-report/png-sync.js.html new file mode 100644 index 0000000..848f6a6 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/png-sync.js.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for png-sync.js + + + + + + + + + +
+
+

All files png-sync.js

+
+ +
+ 83.33% + Statements + 5/6 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 50% + Functions + 1/2 +
+ + +
+ 83.33% + Lines + 5/6 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13  +  +1x +1x +  +1x +176x +  +  +1x +  +  + 
"use strict";
+ 
+let parse = require("./parser-sync");
+let pack = require("./packer-sync");
+ 
+exports.read = function (buffer, options) {
+  return parse(buffer, options || {});
+};
+ 
+exports.write = function (png, options) {
+  return pack(png, options);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/png.js.html b/node_modules/pngjs/coverage/lcov-report/png.js.html new file mode 100644 index 0000000..baa8803 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/png.js.html @@ -0,0 +1,662 @@ + + + + + + Code coverage report for png.js + + + + + + + + + +
+
+

All files png.js

+
+ +
+ 54.17% + Statements + 52/96 +
+ + +
+ 41.18% + Branches + 14/34 +
+ + +
+ 56.25% + Functions + 9/16 +
+ + +
+ 56.52% + Lines + 52/92 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195  +  +1x +1x +1x +1x +1x +  +1x +353x +  +353x +  +  +353x +353x +  +353x +  +  +  +  +353x +  +  +  +353x +353x +  +353x +  +353x +353x +353x +353x +353x +  +  +173x +173x +  +  +  +353x +353x +353x +353x +353x +  +1x +  +1x +  +1x +325x +  +  +  +  +325x +  +325x +  +  +  +325x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +412x +412x +  +  +1x +175x +  +  +1x +174x +174x +  +174x +  +  +1x +149x +  +  +1x +378x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  + 
"use strict";
+ 
+let util = require("util");
+let Stream = require("stream");
+let Parser = require("./parser-async");
+let Packer = require("./packer-async");
+let PNGSync = require("./png-sync");
+ 
+let PNG = (exports.PNG = function (options) {
+  Stream.call(this);
+ 
+  options = options || {}; // eslint-disable-line no-param-reassign
+ 
+  // coerce pixel dimensions to integers (also coerces undefined -> 0):
+  this.width = options.width | 0;
+  this.height = options.height | 0;
+ 
+  this.data =
+    this.width > 0 && this.height > 0
+      ? Buffer.alloc(4 * this.width * this.height)
+      : null;
+ 
+  Iif (options.fill && this.data) {
+    this.data.fill(0);
+  }
+ 
+  this.gamma = 0;
+  this.readable = this.writable = true;
+ 
+  this._parser = new Parser(options);
+ 
+  this._parser.on("error", this.emit.bind(this, "error"));
+  this._parser.on("close", this._handleClose.bind(this));
+  this._parser.on("metadata", this._metadata.bind(this));
+  this._parser.on("gamma", this._gamma.bind(this));
+  this._parser.on(
+    "parsed",
+    function (data) {
+      this.data = data;
+      this.emit("parsed", data);
+    }.bind(this)
+  );
+ 
+  this._packer = new Packer(options);
+  this._packer.on("data", this.emit.bind(this, "data"));
+  this._packer.on("end", this.emit.bind(this, "end"));
+  this._parser.on("close", this._handleClose.bind(this));
+  this._packer.on("error", this.emit.bind(this, "error"));
+});
+util.inherits(PNG, Stream);
+ 
+PNG.sync = PNGSync;
+ 
+PNG.prototype.pack = function () {
+  Iif (!this.data || !this.data.length) {
+    this.emit("error", "No data provided");
+    return this;
+  }
+ 
+  process.nextTick(
+    function () {
+      this._packer.pack(this.data, this.width, this.height, this.gamma);
+    }.bind(this)
+  );
+ 
+  return this;
+};
+ 
+PNG.prototype.parse = function (data, callback) {
+  if (callback) {
+    let onParsed, onError;
+ 
+    onParsed = function (parsedData) {
+      this.removeListener("error", onError);
+ 
+      this.data = parsedData;
+      callback(null, this);
+    }.bind(this);
+ 
+    onError = function (err) {
+      this.removeListener("parsed", onParsed);
+ 
+      callback(err, null);
+    }.bind(this);
+ 
+    this.once("parsed", onParsed);
+    this.once("error", onError);
+  }
+ 
+  this.end(data);
+  return this;
+};
+ 
+PNG.prototype.write = function (data) {
+  this._parser.write(data);
+  return true;
+};
+ 
+PNG.prototype.end = function (data) {
+  this._parser.end(data);
+};
+ 
+PNG.prototype._metadata = function (metadata) {
+  this.width = metadata.width;
+  this.height = metadata.height;
+ 
+  this.emit("metadata", metadata);
+};
+ 
+PNG.prototype._gamma = function (gamma) {
+  this.gamma = gamma;
+};
+ 
+PNG.prototype._handleClose = function () {
+  Iif (!this._parser.writable && !this._packer.readable) {
+    this.emit("close");
+  }
+};
+ 
+PNG.bitblt = function (src, dst, srcX, srcY, width, height, deltaX, deltaY) {
+  // eslint-disable-line max-params
+  // coerce pixel dimensions to integers (also coerces undefined -> 0):
+  /* eslint-disable no-param-reassign */
+  srcX |= 0;
+  srcY |= 0;
+  width |= 0;
+  height |= 0;
+  deltaX |= 0;
+  deltaY |= 0;
+  /* eslint-enable no-param-reassign */
+ 
+  if (
+    srcX > src.width ||
+    srcY > src.height ||
+    srcX + width > src.width ||
+    srcY + height > src.height
+  ) {
+    throw new Error("bitblt reading outside image");
+  }
+ 
+  if (
+    deltaX > dst.width ||
+    deltaY > dst.height ||
+    deltaX + width > dst.width ||
+    deltaY + height > dst.height
+  ) {
+    throw new Error("bitblt writing outside image");
+  }
+ 
+  for (let y = 0; y < height; y++) {
+    src.data.copy(
+      dst.data,
+      ((deltaY + y) * dst.width + deltaX) << 2,
+      ((srcY + y) * src.width + srcX) << 2,
+      ((srcY + y) * src.width + srcX + width) << 2
+    );
+  }
+};
+ 
+PNG.prototype.bitblt = function (
+  dst,
+  srcX,
+  srcY,
+  width,
+  height,
+  deltaX,
+  deltaY
+) {
+  // eslint-disable-line max-params
+ 
+  PNG.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY);
+  return this;
+};
+ 
+PNG.adjustGamma = function (src) {
+  if (src.gamma) {
+    for (let y = 0; y < src.height; y++) {
+      for (let x = 0; x < src.width; x++) {
+        let idx = (src.width * y + x) << 2;
+ 
+        for (let i = 0; i < 3; i++) {
+          let sample = src.data[idx + i] / 255;
+          sample = Math.pow(sample, 1 / 2.2 / src.gamma);
+          src.data[idx + i] = Math.round(sample * 255);
+        }
+      }
+    }
+    src.gamma = 0;
+  }
+};
+ 
+PNG.prototype.adjustGamma = function () {
+  PNG.adjustGamma(this);
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/prettify.css b/node_modules/pngjs/coverage/lcov-report/prettify.css new file mode 100644 index 0000000..006492c --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/prettify.css @@ -0,0 +1,101 @@ +.pln { + color: #000; +} +@media screen { + .str { + color: #080; + } + .kwd { + color: #008; + } + .com { + color: #800; + } + .typ { + color: #606; + } + .lit { + color: #066; + } + .pun, + .opn, + .clo { + color: #660; + } + .tag { + color: #008; + } + .atn { + color: #606; + } + .atv { + color: #080; + } + .dec, + .var { + color: #606; + } + .fun { + color: red; + } +} +@media print, projection { + .str { + color: #060; + } + .kwd { + color: #006; + font-weight: bold; + } + .com { + color: #600; + font-style: italic; + } + .typ { + color: #404; + font-weight: bold; + } + .lit { + color: #044; + } + .pun, + .opn, + .clo { + color: #440; + } + .tag { + color: #006; + font-weight: bold; + } + .atn { + color: #404; + } + .atv { + color: #060; + } +} +pre.prettyprint { + padding: 2px; + border: 1px solid #888; +} +ol.linenums { + margin-top: 0; + margin-bottom: 0; +} +li.L0, +li.L1, +li.L2, +li.L3, +li.L5, +li.L6, +li.L7, +li.L8 { + list-style-type: none; +} +li.L1, +li.L3, +li.L5, +li.L7, +li.L9 { + background: #eee; +} diff --git a/node_modules/pngjs/coverage/lcov-report/prettify.js b/node_modules/pngjs/coverage/lcov-report/prettify.js new file mode 100644 index 0000000..7c0a2fe --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/prettify.js @@ -0,0 +1,1007 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION = true; +(function () { + var h = ["break,continue,do,else,for,if,return,while"]; + var u = [ + h, + "auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile", + ]; + var p = [ + u, + "catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof", + ]; + var l = [ + p, + "alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where", + ]; + var x = [ + p, + "abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient", + ]; + var R = [ + x, + "as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var", + ]; + var r = + "all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes"; + var w = [ + p, + "debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN", + ]; + var s = + "caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"; + var I = [ + h, + "and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None", + ]; + var f = [ + h, + "alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END", + ]; + var H = [h, "case,done,elif,esac,eval,fi,function,in,local,set,then,until"]; + var A = [l, R, w, s + I, f, H]; + var e = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/; + var C = "str"; + var z = "kwd"; + var j = "com"; + var O = "typ"; + var G = "lit"; + var L = "pun"; + var F = "pln"; + var m = "tag"; + var E = "dec"; + var J = "src"; + var P = "atn"; + var n = "atv"; + var N = "nocode"; + var M = + "(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*"; + function k(Z) { + var ad = 0; + var S = false; + var ac = false; + for (var V = 0, U = Z.length; V < U; ++V) { + var ae = Z[V]; + if (ae.ignoreCase) { + ac = true; + } else { + if ( + /[a-z]/i.test( + ae.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, "") + ) + ) { + S = true; + ac = false; + break; + } + } + } + var Y = { b: 8, t: 9, n: 10, v: 11, f: 12, r: 13 }; + function ab(ah) { + var ag = ah.charCodeAt(0); + if (ag !== 92) { + return ag; + } + var af = ah.charAt(1); + ag = Y[af]; + if (ag) { + return ag; + } else { + if ("0" <= af && af <= "7") { + return parseInt(ah.substring(1), 8); + } else { + if (af === "u" || af === "x") { + return parseInt(ah.substring(2), 16); + } else { + return ah.charCodeAt(1); + } + } + } + } + function T(af) { + if (af < 32) { + return (af < 16 ? "\\x0" : "\\x") + af.toString(16); + } + var ag = String.fromCharCode(af); + if (ag === "\\" || ag === "-" || ag === "[" || ag === "]") { + ag = "\\" + ag; + } + return ag; + } + function X(am) { + var aq = am + .substring(1, am.length - 1) + .match( + new RegExp( + "\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]", + "g" + ) + ); + var ak = []; + var af = []; + var ao = aq[0] === "^"; + for (var ar = ao ? 1 : 0, aj = aq.length; ar < aj; ++ar) { + var ah = aq[ar]; + if (/\\[bdsw]/i.test(ah)) { + ak.push(ah); + } else { + var ag = ab(ah); + var al; + if (ar + 2 < aj && "-" === aq[ar + 1]) { + al = ab(aq[ar + 2]); + ar += 2; + } else { + al = ag; + } + af.push([ag, al]); + if (!(al < 65 || ag > 122)) { + if (!(al < 65 || ag > 90)) { + af.push([Math.max(65, ag) | 32, Math.min(al, 90) | 32]); + } + if (!(al < 97 || ag > 122)) { + af.push([Math.max(97, ag) & ~32, Math.min(al, 122) & ~32]); + } + } + } + } + af.sort(function (av, au) { + return av[0] - au[0] || au[1] - av[1]; + }); + var ai = []; + var ap = [NaN, NaN]; + for (var ar = 0; ar < af.length; ++ar) { + var at = af[ar]; + if (at[0] <= ap[1] + 1) { + ap[1] = Math.max(ap[1], at[1]); + } else { + ai.push((ap = at)); + } + } + var an = ["["]; + if (ao) { + an.push("^"); + } + an.push.apply(an, ak); + for (var ar = 0; ar < ai.length; ++ar) { + var at = ai[ar]; + an.push(T(at[0])); + if (at[1] > at[0]) { + if (at[1] + 1 > at[0]) { + an.push("-"); + } + an.push(T(at[1])); + } + } + an.push("]"); + return an.join(""); + } + function W(al) { + var aj = al.source.match( + new RegExp( + "(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)", + "g" + ) + ); + var ah = aj.length; + var an = []; + for (var ak = 0, am = 0; ak < ah; ++ak) { + var ag = aj[ak]; + if (ag === "(") { + ++am; + } else { + if ("\\" === ag.charAt(0)) { + var af = +ag.substring(1); + if (af && af <= am) { + an[af] = -1; + } + } + } + } + for (var ak = 1; ak < an.length; ++ak) { + if (-1 === an[ak]) { + an[ak] = ++ad; + } + } + for (var ak = 0, am = 0; ak < ah; ++ak) { + var ag = aj[ak]; + if (ag === "(") { + ++am; + if (an[am] === undefined) { + aj[ak] = "(?:"; + } + } else { + if ("\\" === ag.charAt(0)) { + var af = +ag.substring(1); + if (af && af <= am) { + aj[ak] = "\\" + an[am]; + } + } + } + } + for (var ak = 0, am = 0; ak < ah; ++ak) { + if ("^" === aj[ak] && "^" !== aj[ak + 1]) { + aj[ak] = ""; + } + } + if (al.ignoreCase && S) { + for (var ak = 0; ak < ah; ++ak) { + var ag = aj[ak]; + var ai = ag.charAt(0); + if (ag.length >= 2 && ai === "[") { + aj[ak] = X(ag); + } else { + if (ai !== "\\") { + aj[ak] = ag.replace(/[a-zA-Z]/g, function (ao) { + var ap = ao.charCodeAt(0); + return "[" + String.fromCharCode(ap & ~32, ap | 32) + "]"; + }); + } + } + } + } + return aj.join(""); + } + var aa = []; + for (var V = 0, U = Z.length; V < U; ++V) { + var ae = Z[V]; + if (ae.global || ae.multiline) { + throw new Error("" + ae); + } + aa.push("(?:" + W(ae) + ")"); + } + return new RegExp(aa.join("|"), ac ? "gi" : "g"); + } + function a(V) { + var U = /(?:^|\s)nocode(?:\s|$)/; + var X = []; + var T = 0; + var Z = []; + var W = 0; + var S; + if (V.currentStyle) { + S = V.currentStyle.whiteSpace; + } else { + if (window.getComputedStyle) { + S = document.defaultView + .getComputedStyle(V, null) + .getPropertyValue("white-space"); + } + } + var Y = S && "pre" === S.substring(0, 3); + function aa(ab) { + switch (ab.nodeType) { + case 1: + if (U.test(ab.className)) { + return; + } + for (var ae = ab.firstChild; ae; ae = ae.nextSibling) { + aa(ae); + } + var ad = ab.nodeName; + if ("BR" === ad || "LI" === ad) { + X[W] = "\n"; + Z[W << 1] = T++; + Z[(W++ << 1) | 1] = ab; + } + break; + case 3: + case 4: + var ac = ab.nodeValue; + if (ac.length) { + if (!Y) { + ac = ac.replace(/[ \t\r\n]+/g, " "); + } else { + ac = ac.replace(/\r\n?/g, "\n"); + } + X[W] = ac; + Z[W << 1] = T; + T += ac.length; + Z[(W++ << 1) | 1] = ab; + } + break; + } + } + aa(V); + return { sourceCode: X.join("").replace(/\n$/, ""), spans: Z }; + } + function B(S, U, W, T) { + if (!U) { + return; + } + var V = { sourceCode: U, basePos: S }; + W(V); + T.push.apply(T, V.decorations); + } + var v = /\S/; + function o(S) { + var V = undefined; + for (var U = S.firstChild; U; U = U.nextSibling) { + var T = U.nodeType; + V = T === 1 ? (V ? S : U) : T === 3 ? (v.test(U.nodeValue) ? S : V) : V; + } + return V === S ? undefined : V; + } + function g(U, T) { + var S = {}; + var V; + (function () { + var ad = U.concat(T); + var ah = []; + var ag = {}; + for (var ab = 0, Z = ad.length; ab < Z; ++ab) { + var Y = ad[ab]; + var ac = Y[3]; + if (ac) { + for (var ae = ac.length; --ae >= 0; ) { + S[ac.charAt(ae)] = Y; + } + } + var af = Y[1]; + var aa = "" + af; + if (!ag.hasOwnProperty(aa)) { + ah.push(af); + ag[aa] = null; + } + } + ah.push(/[\0-\uffff]/); + V = k(ah); + })(); + var X = T.length; + var W = function (ah) { + var Z = ah.sourceCode, + Y = ah.basePos; + var ad = [Y, F]; + var af = 0; + var an = Z.match(V) || []; + var aj = {}; + for (var ae = 0, aq = an.length; ae < aq; ++ae) { + var ag = an[ae]; + var ap = aj[ag]; + var ai = void 0; + var am; + if (typeof ap === "string") { + am = false; + } else { + var aa = S[ag.charAt(0)]; + if (aa) { + ai = ag.match(aa[1]); + ap = aa[0]; + } else { + for (var ao = 0; ao < X; ++ao) { + aa = T[ao]; + ai = ag.match(aa[1]); + if (ai) { + ap = aa[0]; + break; + } + } + if (!ai) { + ap = F; + } + } + am = ap.length >= 5 && "lang-" === ap.substring(0, 5); + if (am && !(ai && typeof ai[1] === "string")) { + am = false; + ap = J; + } + if (!am) { + aj[ag] = ap; + } + } + var ab = af; + af += ag.length; + if (!am) { + ad.push(Y + ab, ap); + } else { + var al = ai[1]; + var ak = ag.indexOf(al); + var ac = ak + al.length; + if (ai[2]) { + ac = ag.length - ai[2].length; + ak = ac - al.length; + } + var ar = ap.substring(5); + B(Y + ab, ag.substring(0, ak), W, ad); + B(Y + ab + ak, al, q(ar, al), ad); + B(Y + ab + ac, ag.substring(ac), W, ad); + } + } + ah.decorations = ad; + }; + return W; + } + function i(T) { + var W = [], + S = []; + if (T.tripleQuotedStrings) { + W.push([ + C, + /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, + null, + "'\"", + ]); + } else { + if (T.multiLineStrings) { + W.push([ + C, + /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/, + null, + "'\"`", + ]); + } else { + W.push([ + C, + /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, + null, + "\"'", + ]); + } + } + if (T.verbatimStrings) { + S.push([C, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]); + } + var Y = T.hashComments; + if (Y) { + if (T.cStyleComments) { + if (Y > 1) { + W.push([j, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, "#"]); + } else { + W.push([ + j, + /^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/, + null, + "#", + ]); + } + S.push([ + C, + /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/, + null, + ]); + } else { + W.push([j, /^#[^\r\n]*/, null, "#"]); + } + } + if (T.cStyleComments) { + S.push([j, /^\/\/[^\r\n]*/, null]); + S.push([j, /^\/\*[\s\S]*?(?:\*\/|$)/, null]); + } + if (T.regexLiterals) { + var X = + "/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/"; + S.push(["lang-regex", new RegExp("^" + M + "(" + X + ")")]); + } + var V = T.types; + if (V) { + S.push([O, V]); + } + var U = ("" + T.keywords).replace(/^ | $/g, ""); + if (U.length) { + S.push([ + z, + new RegExp("^(?:" + U.replace(/[\s,]+/g, "|") + ")\\b"), + null, + ]); + } + W.push([F, /^\s+/, null, " \r\n\t\xA0"]); + S.push( + [G, /^@[a-z_$][a-z_$@0-9]*/i, null], + [O, /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null], + [F, /^[a-z_$][a-z_$@0-9]*/i, null], + [ + G, + new RegExp( + "^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*", + "i" + ), + null, + "0123456789", + ], + [F, /^\\[\s\S]?/, null], + [L, /^.[^\s\w\.$@\'\"\`\/\#\\]*/, null] + ); + return g(W, S); + } + var K = i({ + keywords: A, + hashComments: true, + cStyleComments: true, + multiLineStrings: true, + regexLiterals: true, + }); + function Q(V, ag) { + var U = /(?:^|\s)nocode(?:\s|$)/; + var ab = /\r\n?|\n/; + var ac = V.ownerDocument; + var S; + if (V.currentStyle) { + S = V.currentStyle.whiteSpace; + } else { + if (window.getComputedStyle) { + S = ac.defaultView + .getComputedStyle(V, null) + .getPropertyValue("white-space"); + } + } + var Z = S && "pre" === S.substring(0, 3); + var af = ac.createElement("LI"); + while (V.firstChild) { + af.appendChild(V.firstChild); + } + var W = [af]; + function ae(al) { + switch (al.nodeType) { + case 1: + if (U.test(al.className)) { + break; + } + if ("BR" === al.nodeName) { + ad(al); + if (al.parentNode) { + al.parentNode.removeChild(al); + } + } else { + for (var an = al.firstChild; an; an = an.nextSibling) { + ae(an); + } + } + break; + case 3: + case 4: + if (Z) { + var am = al.nodeValue; + var aj = am.match(ab); + if (aj) { + var ai = am.substring(0, aj.index); + al.nodeValue = ai; + var ah = am.substring(aj.index + aj[0].length); + if (ah) { + var ak = al.parentNode; + ak.insertBefore(ac.createTextNode(ah), al.nextSibling); + } + ad(al); + if (!ai) { + al.parentNode.removeChild(al); + } + } + } + break; + } + } + function ad(ak) { + while (!ak.nextSibling) { + ak = ak.parentNode; + if (!ak) { + return; + } + } + function ai(al, ar) { + var aq = ar ? al.cloneNode(false) : al; + var ao = al.parentNode; + if (ao) { + var ap = ai(ao, 1); + var an = al.nextSibling; + ap.appendChild(aq); + for (var am = an; am; am = an) { + an = am.nextSibling; + ap.appendChild(am); + } + } + return aq; + } + var ah = ai(ak.nextSibling, 0); + for (var aj; (aj = ah.parentNode) && aj.nodeType === 1; ) { + ah = aj; + } + W.push(ah); + } + for (var Y = 0; Y < W.length; ++Y) { + ae(W[Y]); + } + if (ag === (ag | 0)) { + W[0].setAttribute("value", ag); + } + var aa = ac.createElement("OL"); + aa.className = "linenums"; + var X = Math.max(0, (ag - 1) | 0) || 0; + for (var Y = 0, T = W.length; Y < T; ++Y) { + af = W[Y]; + af.className = "L" + ((Y + X) % 10); + if (!af.firstChild) { + af.appendChild(ac.createTextNode("\xA0")); + } + aa.appendChild(af); + } + V.appendChild(aa); + } + function D(ac) { + var aj = /\bMSIE\b/.test(navigator.userAgent); + var am = /\n/g; + var al = ac.sourceCode; + var an = al.length; + var V = 0; + var aa = ac.spans; + var T = aa.length; + var ah = 0; + var X = ac.decorations; + var Y = X.length; + var Z = 0; + X[Y] = an; + var ar, aq; + for (aq = ar = 0; aq < Y; ) { + if (X[aq] !== X[aq + 2]) { + X[ar++] = X[aq++]; + X[ar++] = X[aq++]; + } else { + aq += 2; + } + } + Y = ar; + for (aq = ar = 0; aq < Y; ) { + var at = X[aq]; + var ab = X[aq + 1]; + var W = aq + 2; + while (W + 2 <= Y && X[W + 1] === ab) { + W += 2; + } + X[ar++] = at; + X[ar++] = ab; + aq = W; + } + Y = X.length = ar; + var ae = null; + while (ah < T) { + var af = aa[ah]; + var S = aa[ah + 2] || an; + var ag = X[Z]; + var ap = X[Z + 2] || an; + var W = Math.min(S, ap); + var ak = aa[ah + 1]; + var U; + if (ak.nodeType !== 1 && (U = al.substring(V, W))) { + if (aj) { + U = U.replace(am, "\r"); + } + ak.nodeValue = U; + var ai = ak.ownerDocument; + var ao = ai.createElement("SPAN"); + ao.className = X[Z + 1]; + var ad = ak.parentNode; + ad.replaceChild(ao, ak); + ao.appendChild(ak); + if (V < S) { + aa[ah + 1] = ak = ai.createTextNode(al.substring(W, S)); + ad.insertBefore(ak, ao.nextSibling); + } + } + V = W; + if (V >= S) { + ah += 2; + } + if (V >= ap) { + Z += 2; + } + } + } + var t = {}; + function c(U, V) { + for (var S = V.length; --S >= 0; ) { + var T = V[S]; + if (!t.hasOwnProperty(T)) { + t[T] = U; + } else { + if (window.console) { + console.warn("cannot override language handler %s", T); + } + } + } + } + function q(T, S) { + if (!(T && t.hasOwnProperty(T))) { + T = /^\s*]*(?:>|$)/], + [j, /^<\!--[\s\S]*?(?:-\->|$)/], + ["lang-", /^<\?([\s\S]+?)(?:\?>|$)/], + ["lang-", /^<%([\s\S]+?)(?:%>|$)/], + [L, /^(?:<[%?]|[%?]>)/], + ["lang-", /^]*>([\s\S]+?)<\/xmp\b[^>]*>/i], + ["lang-js", /^]*>([\s\S]*?)(<\/script\b[^>]*>)/i], + ["lang-css", /^]*>([\s\S]*?)(<\/style\b[^>]*>)/i], + ["lang-in.tag", /^(<\/?[a-z][^<>]*>)/i], + ] + ), + ["default-markup", "htm", "html", "mxml", "xhtml", "xml", "xsl"] + ); + c( + g( + [ + [F, /^[\s]+/, null, " \t\r\n"], + [n, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, "\"'"], + ], + [ + [m, /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i], + [P, /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i], + ["lang-uq.val", /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/], + [L, /^[=<>\/]+/], + ["lang-js", /^on\w+\s*=\s*\"([^\"]+)\"/i], + ["lang-js", /^on\w+\s*=\s*\'([^\']+)\'/i], + ["lang-js", /^on\w+\s*=\s*([^\"\'>\s]+)/i], + ["lang-css", /^style\s*=\s*\"([^\"]+)\"/i], + ["lang-css", /^style\s*=\s*\'([^\']+)\'/i], + ["lang-css", /^style\s*=\s*([^\"\'>\s]+)/i], + ] + ), + ["in.tag"] + ); + c(g([], [[n, /^[\s\S]+/]]), ["uq.val"]); + c(i({ keywords: l, hashComments: true, cStyleComments: true, types: e }), [ + "c", + "cc", + "cpp", + "cxx", + "cyc", + "m", + ]); + c(i({ keywords: "null,true,false" }), ["json"]); + c( + i({ + keywords: R, + hashComments: true, + cStyleComments: true, + verbatimStrings: true, + types: e, + }), + ["cs"] + ); + c(i({ keywords: x, cStyleComments: true }), ["java"]); + c(i({ keywords: H, hashComments: true, multiLineStrings: true }), [ + "bsh", + "csh", + "sh", + ]); + c( + i({ + keywords: I, + hashComments: true, + multiLineStrings: true, + tripleQuotedStrings: true, + }), + ["cv", "py"] + ); + c( + i({ + keywords: s, + hashComments: true, + multiLineStrings: true, + regexLiterals: true, + }), + ["perl", "pl", "pm"] + ); + c( + i({ + keywords: f, + hashComments: true, + multiLineStrings: true, + regexLiterals: true, + }), + ["rb"] + ); + c(i({ keywords: w, cStyleComments: true, regexLiterals: true }), ["js"]); + c( + i({ + keywords: r, + hashComments: 3, + cStyleComments: true, + multilineStrings: true, + tripleQuotedStrings: true, + regexLiterals: true, + }), + ["coffee"] + ); + c(g([], [[C, /^[\s\S]+/]]), ["regex"]); + function d(V) { + var U = V.langExtension; + try { + var S = a(V.sourceNode); + var T = S.sourceCode; + V.sourceCode = T; + V.spans = S.spans; + V.basePos = 0; + q(U, T)(V); + D(V); + } catch (W) { + if ("console" in window) { + console.log(W && W.stack ? W.stack : W); + } + } + } + function y(W, V, U) { + var S = document.createElement("PRE"); + S.innerHTML = W; + if (U) { + Q(S, U); + } + var T = { langExtension: V, numberLines: U, sourceNode: S }; + d(T); + return S.innerHTML; + } + function b(ad) { + function Y(af) { + return document.getElementsByTagName(af); + } + var ac = [Y("pre"), Y("code"), Y("xmp")]; + var T = []; + for (var aa = 0; aa < ac.length; ++aa) { + for (var Z = 0, V = ac[aa].length; Z < V; ++Z) { + T.push(ac[aa][Z]); + } + } + ac = null; + var W = Date; + if (!W.now) { + W = { + now: function () { + return +new Date(); + }, + }; + } + var X = 0; + var S; + var ab = /\blang(?:uage)?-([\w.]+)(?!\S)/; + var ae = /\bprettyprint\b/; + function U() { + var ag = window.PR_SHOULD_USE_CONTINUATION ? W.now() + 250 : Infinity; + for (; X < T.length && W.now() < ag; X++) { + var aj = T[X]; + var ai = aj.className; + if (ai.indexOf("prettyprint") >= 0) { + var ah = ai.match(ab); + var am; + if (!ah && (am = o(aj)) && "CODE" === am.tagName) { + ah = am.className.match(ab); + } + if (ah) { + ah = ah[1]; + } + var al = false; + for (var ak = aj.parentNode; ak; ak = ak.parentNode) { + if ( + (ak.tagName === "pre" || + ak.tagName === "code" || + ak.tagName === "xmp") && + ak.className && + ak.className.indexOf("prettyprint") >= 0 + ) { + al = true; + break; + } + } + if (!al) { + var af = aj.className.match(/\blinenums\b(?::(\d+))?/); + af = af ? (af[1] && af[1].length ? +af[1] : true) : false; + if (af) { + Q(aj, af); + } + S = { langExtension: ah, sourceNode: aj, numberLines: af }; + d(S); + } + } + } + if (X < T.length) { + setTimeout(U, 250); + } else { + if (ad) { + ad(); + } + } + } + U(); + } + window.prettyPrintOne = y; + window.prettyPrint = b; + window.PR = { + createSimpleLexer: g, + registerLangHandler: c, + sourceDecorator: i, + PR_ATTRIB_NAME: P, + PR_ATTRIB_VALUE: n, + PR_COMMENT: j, + PR_DECLARATION: E, + PR_KEYWORD: z, + PR_LITERAL: G, + PR_NOCODE: N, + PR_PLAIN: F, + PR_PUNCTUATION: L, + PR_SOURCE: J, + PR_STRING: C, + PR_TAG: m, + PR_TYPE: O, + }; +})(); +PR.registerLangHandler( + PR.createSimpleLexer( + [], + [ + [PR.PR_DECLARATION, /^]*(?:>|$)/], + [PR.PR_COMMENT, /^<\!--[\s\S]*?(?:-\->|$)/], + [PR.PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/], + ["lang-", /^<\?([\s\S]+?)(?:\?>|$)/], + ["lang-", /^<%([\s\S]+?)(?:%>|$)/], + ["lang-", /^]*>([\s\S]+?)<\/xmp\b[^>]*>/i], + [ + "lang-handlebars", + /^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i, + ], + ["lang-js", /^]*>([\s\S]*?)(<\/script\b[^>]*>)/i], + ["lang-css", /^]*>([\s\S]*?)(<\/style\b[^>]*>)/i], + ["lang-in.tag", /^(<\/?[a-z][^<>]*>)/i], + [PR.PR_DECLARATION, /^{{[#^>/]?\s*[\w.][^}]*}}/], + [PR.PR_DECLARATION, /^{{&?\s*[\w.][^}]*}}/], + [PR.PR_DECLARATION, /^{{{>?\s*[\w.][^}]*}}}/], + [PR.PR_COMMENT, /^{{![^}]*}}/], + ] + ), + ["handlebars", "hbs"] +); +PR.registerLangHandler( + PR.createSimpleLexer( + [[PR.PR_PLAIN, /^[ \t\r\n\f]+/, null, " \t\r\n\f"]], + [ + [ + PR.PR_STRING, + /^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/, + null, + ], + [ + PR.PR_STRING, + /^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/, + null, + ], + ["lang-css-str", /^url\(([^\)\"\']*)\)/i], + [ + PR.PR_KEYWORD, + /^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i, + null, + ], + [ + "lang-css-kw", + /^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i, + ], + [PR.PR_COMMENT, /^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//], + [PR.PR_COMMENT, /^(?:)/], + [PR.PR_LITERAL, /^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i], + [PR.PR_LITERAL, /^#(?:[0-9a-f]{3}){1,2}/i], + [ + PR.PR_PLAIN, + /^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i, + ], + [PR.PR_PUNCTUATION, /^[^\s\w\'\"]+/], + ] + ), + ["css"] +); +PR.registerLangHandler( + PR.createSimpleLexer( + [], + [ + [ + PR.PR_KEYWORD, + /^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i, + ], + ] + ), + ["css-kw"] +); +PR.registerLangHandler( + PR.createSimpleLexer([], [[PR.PR_STRING, /^[^\)\"\']+/]]), + ["css-str"] +); diff --git a/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png b/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 0000000..03f704a Binary files /dev/null and b/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png differ diff --git a/node_modules/pngjs/coverage/lcov-report/sorter.js b/node_modules/pngjs/coverage/lcov-report/sorter.js new file mode 100644 index 0000000..418a5b1 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/sorter.js @@ -0,0 +1,169 @@ +/* eslint-disable */ +var addSorting = (function () { + "use strict"; + var cols, + currentSort = { + index: 0, + desc: false, + }; + + // returns the summary table element + function getTable() { + return document.querySelector(".coverage-summary"); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector("thead tr"); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector("tbody"); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll("th")[n]; + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll("th"), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute("data-col"), + sortable: !colNode.getAttribute("data-nosort"), + type: colNode.getAttribute("data-type") || "string", + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === "number"; + colNode.innerHTML = colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll("td"), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute("data-value"); + if (col.type === "number") { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll("tr"), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function (a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector(".coverage-summary tbody"), + rowNodes = tableBody.querySelectorAll("tr"), + rows = [], + i; + + if (desc) { + finalSorter = function (a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, "").replace(/ sorted-desc$/, ""); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? " sorted-desc" + : " sorted"; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function () { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector(".sorter").parentElement; + if (el.addEventListener) { + el.addEventListener("click", ithSorter(i)); + } else { + el.attachEvent("onclick", ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function () { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener("load", addSorting); diff --git a/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html b/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html new file mode 100644 index 0000000..9ae5a14 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html @@ -0,0 +1,584 @@ + + + + + + Code coverage report for sync-inflate.js + + + + + + + + + +
+
+

All files sync-inflate.js

+
+ +
+ 75.31% + Statements + 61/81 +
+ + +
+ 62% + Branches + 31/50 +
+ + +
+ 87.5% + Functions + 7/8 +
+ + +
+ 75.31% + Lines + 61/81 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169  +  +1x +1x +1x +  +1x +  +  +127x +  +  +  +127x +9x +  +  +127x +  +  +127x +127x +  +127x +127x +  +  +  +  +  +  +  +  +126x +  +  +  +  +126x +  +  +  +126x +126x +  +  +1x +127x +  +  +  +127x +  +127x +127x +127x +127x +  +127x +127x +  +  +127x +1x +  +  +  +126x +  +  +  +126x +126x +  +126x +126x +126x +  +126x +9x +  +  +126x +126x +126x +  +126x +126x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +127x +  +127x +127x +  +  +  +  +  +  +  +  +  +127x +  +  +127x +1x +  +  +126x +  +  +  +  +  +  +  +  +126x +126x +  +126x +  +  +1x +  +  +127x +  +  +127x +  +  +  +127x +127x +  +  +  +127x +  +  +  +127x +  +  +1x +1x +1x +1x + 
"use strict";
+ 
+let assert = require("assert").ok;
+let zlib = require("zlib");
+let util = require("util");
+ 
+let kMaxLength = require("buffer").kMaxLength;
+ 
+function Inflate(opts) {
+  Iif (!(this instanceof Inflate)) {
+    return new Inflate(opts);
+  }
+ 
+  if (opts && opts.chunkSize < zlib.Z_MIN_CHUNK) {
+    opts.chunkSize = zlib.Z_MIN_CHUNK;
+  }
+ 
+  zlib.Inflate.call(this, opts);
+ 
+  // Node 8 --> 9 compatibility check
+  this._offset = this._offset === undefined ? this._outOffset : this._offset;
+  this._buffer = this._buffer || this._outBuffer;
+ 
+  Eif (opts && opts.maxLength != null) {
+    this._maxLength = opts.maxLength;
+  }
+}
+ 
+function createInflate(opts) {
+  return new Inflate(opts);
+}
+ 
+function _close(engine, callback) {
+  Iif (callback) {
+    process.nextTick(callback);
+  }
+ 
+  // Caller may invoke .close after a zlib error (which will null _handle).
+  Iif (!engine._handle) {
+    return;
+  }
+ 
+  engine._handle.close();
+  engine._handle = null;
+}
+ 
+Inflate.prototype._processChunk = function (chunk, flushFlag, asyncCb) {
+  Iif (typeof asyncCb === "function") {
+    return zlib.Inflate._processChunk.call(this, chunk, flushFlag, asyncCb);
+  }
+ 
+  let self = this;
+ 
+  let availInBefore = chunk && chunk.length;
+  let availOutBefore = this._chunkSize - this._offset;
+  let leftToInflate = this._maxLength;
+  let inOff = 0;
+ 
+  let buffers = [];
+  let nread = 0;
+ 
+  let error;
+  this.on("error", function (err) {
+    error = err;
+  });
+ 
+  function handleChunk(availInAfter, availOutAfter) {
+    Iif (self._hadError) {
+      return;
+    }
+ 
+    let have = availOutBefore - availOutAfter;
+    assert(have >= 0, "have should not go down");
+ 
+    Eif (have > 0) {
+      let out = self._buffer.slice(self._offset, self._offset + have);
+      self._offset += have;
+ 
+      if (out.length > leftToInflate) {
+        out = out.slice(0, leftToInflate);
+      }
+ 
+      buffers.push(out);
+      nread += out.length;
+      leftToInflate -= out.length;
+ 
+      Eif (leftToInflate === 0) {
+        return false;
+      }
+    }
+ 
+    if (availOutAfter === 0 || self._offset >= self._chunkSize) {
+      availOutBefore = self._chunkSize;
+      self._offset = 0;
+      self._buffer = Buffer.allocUnsafe(self._chunkSize);
+    }
+ 
+    if (availOutAfter === 0) {
+      inOff += availInBefore - availInAfter;
+      availInBefore = availInAfter;
+ 
+      return true;
+    }
+ 
+    return false;
+  }
+ 
+  assert(this._handle, "zlib binding closed");
+  let res;
+  do {
+    res = this._handle.writeSync(
+      flushFlag,
+      chunk, // in
+      inOff, // in_off
+      availInBefore, // in_len
+      this._buffer, // out
+      this._offset, //out_off
+      availOutBefore
+    ); // out_len
+    // Node 8 --> 9 compatibility check
+    res = res || this._writeState;
+  } while (!this._hadError && handleChunk(res[0], res[1]));
+ 
+  if (this._hadError) {
+    throw error;
+  }
+ 
+  Iif (nread >= kMaxLength) {
+    _close(this);
+    throw new RangeError(
+      "Cannot create final Buffer. It would be larger than 0x" +
+        kMaxLength.toString(16) +
+        " bytes"
+    );
+  }
+ 
+  let buf = Buffer.concat(buffers, nread);
+  _close(this);
+ 
+  return buf;
+};
+ 
+util.inherits(Inflate, zlib.Inflate);
+ 
+function zlibBufferSync(engine, buffer) {
+  Iif (typeof buffer === "string") {
+    buffer = Buffer.from(buffer);
+  }
+  Iif (!(buffer instanceof Buffer)) {
+    throw new TypeError("Not a string or buffer");
+  }
+ 
+  let flushFlag = engine._finishFlushFlag;
+  Iif (flushFlag == null) {
+    flushFlag = zlib.Z_FINISH;
+  }
+ 
+  return engine._processChunk(buffer, flushFlag);
+}
+ 
+function inflateSync(buffer, opts) {
+  return zlibBufferSync(new Inflate(opts), buffer);
+}
+ 
+module.exports = exports = inflateSync;
+exports.Inflate = Inflate;
+exports.createInflate = createInflate;
+exports.inflateSync = inflateSync;
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html b/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html new file mode 100644 index 0000000..576dd88 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html @@ -0,0 +1,215 @@ + + + + + + Code coverage report for sync-reader.js + + + + + + + + + +
+
+

All files sync-reader.js

+
+ +
+ 88.89% + Statements + 16/18 +
+ + +
+ 72.73% + Branches + 8/11 +
+ + +
+ 100% + Functions + 3/3 +
+ + +
+ 88.89% + Lines + 16/18 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46  +  +1x +338x +338x +  +  +1x +9900x +  +  +  +  +  +  +1x +  +338x +9900x +  +9900x +  +  +  +  +9900x +  +9900x +  +9900x +  +9900x +  +  +  +  +  +338x +  +  +  +338x +13x +  +  + 
"use strict";
+ 
+let SyncReader = (module.exports = function (buffer) {
+  this._buffer = buffer;
+  this._reads = [];
+});
+ 
+SyncReader.prototype.read = function (length, callback) {
+  this._reads.push({
+    length: Math.abs(length), // if length < 0 then at most this length
+    allowLess: length < 0,
+    func: callback,
+  });
+};
+ 
+SyncReader.prototype.process = function () {
+  // as long as there is any data and read requests
+  while (this._reads.length > 0 && this._buffer.length) {
+    let read = this._reads[0];
+ 
+    Eif (
+      this._buffer.length &&
+      (this._buffer.length >= read.length || read.allowLess)
+    ) {
+      // ok there is any data so that we can satisfy this request
+      this._reads.shift(); // == read
+ 
+      let buf = this._buffer;
+ 
+      this._buffer = buf.slice(read.length);
+ 
+      read.func.call(this, buf.slice(0, read.length));
+    } else {
+      break;
+    }
+  }
+ 
+  Iif (this._reads.length > 0) {
+    return new Error("There are some read requests waitng on finished stream");
+  }
+ 
+  if (this._buffer.length > 0) {
+    return new Error("unrecognised content at end of stream");
+  }
+};
+ 
+ +
+
+ + + + + + + + + \ No newline at end of file diff --git a/node_modules/pngjs/coverage/lcov.info b/node_modules/pngjs/coverage/lcov.info new file mode 100644 index 0000000..1a7a647 --- /dev/null +++ b/node_modules/pngjs/coverage/lcov.info @@ -0,0 +1,2177 @@ +TN: +SF:lib\bitmapper.js +FN:7,(anonymous_0) +FN:11,(anonymous_1) +FN:25,(anonymous_2) +FN:39,(anonymous_3) +FN:52,(anonymous_4) +FN:66,(anonymous_5) +FN:70,(anonymous_6) +FN:80,(anonymous_7) +FN:90,(anonymous_8) +FN:99,(anonymous_9) +FN:107,bitRetriever +FN:111,split +FN:153,(anonymous_12) +FN:161,(anonymous_13) +FN:164,(anonymous_14) +FN:172,mapImage8Bit +FN:187,mapImageCustomBit +FN:202,(anonymous_17) +FN:229,(anonymous_18) +FNF:19 +FNH:17 +FNDA:0,(anonymous_0) +FNDA:313632,(anonymous_1) +FNDA:8192,(anonymous_2) +FNDA:1228160,(anonymous_3) +FNDA:272640,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:1193380,(anonymous_6) +FNDA:8192,(anonymous_7) +FNDA:24576,(anonymous_8) +FNDA:8192,(anonymous_9) +FNDA:209,bitRetriever +FNDA:334250,split +FNDA:1234340,(anonymous_12) +FNDA:8106,(anonymous_13) +FNDA:209,(anonymous_14) +FNDA:210,mapImage8Bit +FNDA:529,mapImageCustomBit +FNDA:335,(anonymous_17) +FNDA:2732114,(anonymous_18) +DA:3,1 +DA:5,1 +DA:12,313632 +DA:13,0 +DA:16,313632 +DA:17,313632 +DA:18,313632 +DA:19,313632 +DA:20,313632 +DA:26,8192 +DA:27,0 +DA:30,8192 +DA:31,8192 +DA:32,8192 +DA:33,8192 +DA:34,8192 +DA:40,1228160 +DA:41,0 +DA:44,1228160 +DA:45,1228160 +DA:46,1228160 +DA:47,1228160 +DA:53,272640 +DA:54,0 +DA:57,272640 +DA:58,272640 +DA:59,272640 +DA:60,272640 +DA:64,1 +DA:71,1193380 +DA:72,1193380 +DA:73,1193380 +DA:74,1193380 +DA:75,1193380 +DA:81,8192 +DA:82,8192 +DA:83,8192 +DA:84,8192 +DA:85,8192 +DA:91,24576 +DA:92,24576 +DA:93,24576 +DA:94,24576 +DA:100,8192 +DA:101,8192 +DA:102,8192 +DA:103,8192 +DA:108,209 +DA:109,209 +DA:112,334250 +DA:113,0 +DA:115,334250 +DA:116,334250 +DA:118,334250 +DA:120,0 +DA:122,149504 +DA:123,149504 +DA:124,149504 +DA:125,149504 +DA:127,49612 +DA:128,49612 +DA:129,49612 +DA:130,49612 +DA:132,2968 +DA:133,2968 +DA:134,2968 +DA:135,2968 +DA:136,2968 +DA:137,2968 +DA:139,132166 +DA:140,132166 +DA:141,132166 +DA:142,132166 +DA:143,132166 +DA:144,132166 +DA:145,132166 +DA:146,132166 +DA:147,132166 +DA:148,132166 +DA:152,209 +DA:154,1234340 +DA:155,334250 +DA:157,1234340 +DA:158,1234340 +DA:159,1234340 +DA:162,8106 +DA:165,209 +DA:166,0 +DA:174,210 +DA:175,210 +DA:176,210 +DA:177,210 +DA:178,7288 +DA:179,1822624 +DA:180,1822624 +DA:181,1822624 +DA:184,210 +DA:189,529 +DA:190,529 +DA:191,529 +DA:192,529 +DA:193,8106 +DA:194,1234340 +DA:195,1234340 +DA:196,1234340 +DA:198,8106 +DA:202,1 +DA:203,335 +DA:204,335 +DA:205,335 +DA:206,335 +DA:207,335 +DA:210,335 +DA:211,209 +DA:214,335 +DA:215,269 +DA:217,66 +DA:219,335 +DA:220,335 +DA:224,335 +DA:225,72 +DA:226,72 +DA:228,263 +DA:229,263 +DA:230,2732114 +DA:231,2732114 +DA:232,2732114 +DA:234,263 +DA:237,335 +DA:238,739 +DA:239,210 +DA:248,529 +DA:258,335 +DA:259,126 +DA:260,0 +DA:263,209 +DA:266,335 +LF:137 +LH:129 +BRDA:12,0,0,0 +BRDA:12,0,1,313632 +BRDA:26,1,0,0 +BRDA:26,1,1,8192 +BRDA:40,2,0,0 +BRDA:40,2,1,1228160 +BRDA:53,3,0,0 +BRDA:53,3,1,272640 +BRDA:112,4,0,0 +BRDA:112,4,1,334250 +BRDA:118,5,0,0 +BRDA:118,5,1,149504 +BRDA:118,5,2,49612 +BRDA:118,5,3,2968 +BRDA:118,5,4,132166 +BRDA:165,6,0,0 +BRDA:165,6,1,209 +BRDA:210,7,0,209 +BRDA:210,7,1,126 +BRDA:214,8,0,269 +BRDA:214,8,1,66 +BRDA:224,9,0,72 +BRDA:224,9,1,263 +BRDA:238,10,0,210 +BRDA:238,10,1,529 +BRDA:258,11,0,126 +BRDA:258,11,1,209 +BRDA:259,12,0,0 +BRDA:259,12,1,126 +BRF:29 +BRH:21 +end_of_record +TN: +SF:lib\bitpacker.js +FN:5,(anonymous_0) +FN:11,(anonymous_1) +FN:52,getRGBA +FNF:3 +FNH:2 +FNDA:325,(anonymous_0) +FNDA:325,(anonymous_1) +FNDA:0,getRGBA +DA:3,1 +DA:5,1 +DA:7,325 +DA:10,325 +DA:11,325 +DA:12,325 +DA:13,325 +DA:15,325 +DA:18,325 +DA:19,325 +DA:24,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:36,0 +DA:38,0 +DA:39,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:48,0 +DA:49,0 +DA:56,0 +DA:57,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:81,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:95,0 +DA:99,0 +DA:105,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:112,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:123,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:130,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:138,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:146,0 +DA:149,0 +DA:152,0 +DA:153,0 +DA:157,0 +LF:86 +LH:10 +BRDA:10,0,0,325 +BRDA:10,0,1,0 +BRDA:18,1,0,325 +BRDA:18,1,1,0 +BRDA:18,2,0,325 +BRDA:18,2,1,0 +BRDA:18,2,2,0 +BRDA:24,3,0,0 +BRDA:24,3,1,0 +BRDA:28,4,0,0 +BRDA:28,4,1,0 +BRDA:28,5,0,0 +BRDA:28,5,1,0 +BRDA:32,6,0,0 +BRDA:32,6,1,0 +BRDA:41,7,0,0 +BRDA:41,7,1,0 +BRDA:42,8,0,0 +BRDA:42,8,1,0 +BRDA:45,9,0,0 +BRDA:45,9,1,0 +BRDA:48,10,0,0 +BRDA:48,10,1,0 +BRDA:57,11,0,0 +BRDA:57,11,1,0 +BRDA:57,11,2,0 +BRDA:57,11,3,0 +BRDA:57,11,4,0 +BRDA:88,12,0,0 +BRDA:88,12,1,0 +BRDA:89,13,0,0 +BRDA:89,13,1,0 +BRDA:112,14,0,0 +BRDA:112,14,1,0 +BRDA:112,14,2,0 +BRDA:112,14,3,0 +BRDA:112,14,4,0 +BRDA:115,15,0,0 +BRDA:115,15,1,0 +BRDA:119,16,0,0 +BRDA:119,16,1,0 +BRDA:126,17,0,0 +BRDA:126,17,1,0 +BRDA:135,18,0,0 +BRDA:135,18,1,0 +BRDA:137,19,0,0 +BRDA:137,19,1,0 +BRDA:142,20,0,0 +BRDA:142,20,1,0 +BRF:49 +BRH:3 +end_of_record +TN: +SF:lib\chunkstream.js +FN:6,(anonymous_0) +FN:20,(anonymous_1) +FN:28,(anonymous_2) +FN:41,(anonymous_3) +FN:67,(anonymous_4) +FN:90,(anonymous_5) +FN:98,(anonymous_6) +FN:110,(anonymous_7) +FN:132,(anonymous_8) +FN:163,(anonymous_9) +FNF:10 +FNH:10 +FNDA:529,(anonymous_0) +FNDA:13318,(anonymous_1) +FNDA:13318,(anonymous_2) +FNDA:943,(anonymous_3) +FNDA:311,(anonymous_4) +FNDA:311,(anonymous_5) +FNDA:327,(anonymous_6) +FNDA:741,(anonymous_7) +FNDA:12408,(anonymous_8) +FNDA:14263,(anonymous_9) +DA:3,1 +DA:4,1 +DA:6,1 +DA:7,529 +DA:9,529 +DA:10,529 +DA:12,529 +DA:13,529 +DA:15,529 +DA:16,529 +DA:18,1 +DA:20,1 +DA:21,13318 +DA:27,13318 +DA:29,13318 +DA:32,13318 +DA:33,0 +DA:35,0 +DA:41,1 +DA:42,943 +DA:43,0 +DA:44,0 +DA:48,943 +DA:49,943 +DA:51,0 +DA:54,943 +DA:55,943 +DA:57,943 +DA:60,943 +DA:61,346 +DA:64,943 +DA:67,1 +DA:68,311 +DA:69,0 +DA:72,311 +DA:75,311 +DA:76,0 +DA:80,311 +DA:81,309 +DA:83,2 +DA:84,2 +DA:88,1 +DA:90,1 +DA:91,311 +DA:92,3 +DA:95,311 +DA:98,1 +DA:99,327 +DA:100,0 +DA:103,327 +DA:104,327 +DA:105,327 +DA:107,327 +DA:110,1 +DA:112,741 +DA:115,741 +DA:118,741 +DA:119,568 +DA:120,568 +DA:122,568 +DA:125,173 +DA:126,173 +DA:128,173 +DA:132,1 +DA:133,12408 +DA:135,12408 +DA:136,12408 +DA:137,12408 +DA:140,12408 +DA:141,12617 +DA:142,12617 +DA:144,12617 +DA:145,12617 +DA:148,12617 +DA:149,11863 +DA:154,12408 +DA:155,532 +DA:158,12408 +DA:160,12408 +DA:163,1 +DA:164,14263 +DA:166,14263 +DA:167,15656 +DA:170,15656 +DA:171,741 +DA:172,14915 +DA:175,12408 +DA:179,2507 +DA:183,14263 +DA:184,2 +DA:187,0 +LF:91 +LH:82 +BRDA:32,0,0,0 +BRDA:32,0,1,13318 +BRDA:32,1,0,13318 +BRDA:32,1,1,10215 +BRDA:42,2,0,0 +BRDA:42,2,1,943 +BRDA:48,3,0,943 +BRDA:48,3,1,0 +BRDA:51,4,0,0 +BRDA:51,4,1,0 +BRDA:60,5,0,346 +BRDA:60,5,1,597 +BRDA:60,6,0,943 +BRDA:60,6,1,929 +BRDA:64,7,0,943 +BRDA:64,7,1,929 +BRDA:68,8,0,0 +BRDA:68,8,1,311 +BRDA:75,9,0,0 +BRDA:75,9,1,311 +BRDA:80,10,0,309 +BRDA:80,10,1,2 +BRDA:91,11,0,3 +BRDA:91,11,1,308 +BRDA:99,12,0,0 +BRDA:99,12,1,327 +BRDA:118,13,0,568 +BRDA:118,13,1,173 +BRDA:148,14,0,11863 +BRDA:148,14,1,754 +BRDA:154,15,0,532 +BRDA:154,15,1,11876 +BRDA:166,16,0,27412 +BRDA:166,16,1,15708 +BRDA:166,16,2,15671 +BRDA:170,17,0,741 +BRDA:170,17,1,14915 +BRDA:172,18,0,12408 +BRDA:172,18,1,2507 +BRDA:183,19,0,2 +BRDA:183,19,1,14261 +BRDA:183,20,0,14263 +BRDA:183,20,1,14213 +BRF:43 +BRH:35 +end_of_record +TN: +SF:lib\constants.js +FNF:0 +FNH:0 +DA:3,1 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:lib\crc.js +FN:5,(anonymous_0) +FN:19,(anonymous_1) +FN:23,(anonymous_2) +FN:30,(anonymous_3) +FN:34,(anonymous_4) +FNF:5 +FNH:5 +FNDA:1,(anonymous_0) +FNDA:2461,(anonymous_1) +FNDA:4839,(anonymous_2) +FNDA:2195,(anonymous_3) +FNDA:1592,(anonymous_4) +DA:3,1 +DA:5,1 +DA:6,1 +DA:7,256 +DA:8,256 +DA:9,2048 +DA:10,1024 +DA:12,1024 +DA:15,256 +DA:19,1 +DA:20,2461 +DA:23,1 +DA:24,4839 +DA:25,823519 +DA:27,4839 +DA:30,1 +DA:31,2195 +DA:34,1 +DA:35,1592 +DA:36,1592 +DA:37,305287 +DA:39,1592 +LF:22 +LH:22 +BRDA:9,0,0,1024 +BRDA:9,0,1,1024 +BRF:2 +BRH:2 +end_of_record +TN: +SF:lib\filter-pack.js +FN:5,filterNone +FN:11,filterSumNone +FN:21,filterSub +FN:30,filterSumSub +FN:42,filterUp +FN:51,filterSumUp +FN:64,filterAvg +FN:74,filterSumAvg +FN:87,filterPaeth +FN:99,filterSumPaeth +FN:130,(anonymous_10) +FNF:11 +FNH:11 +FNDA:44,filterNone +FNDA:10490,filterSumNone +FNDA:637,filterSub +FNDA:10490,filterSumSub +FNDA:2670,filterUp +FNDA:10490,filterSumUp +FNDA:208,filterAvg +FNDA:10490,filterSumAvg +FNDA:6931,filterPaeth +FNDA:10490,filterSumPaeth +FNDA:325,(anonymous_10) +DA:3,1 +DA:6,44 +DA:7,5136 +DA:12,10490 +DA:13,10490 +DA:15,10490 +DA:16,2776736 +DA:18,10490 +DA:22,637 +DA:23,107032 +DA:24,107032 +DA:26,107032 +DA:31,10490 +DA:32,10490 +DA:33,2776736 +DA:34,2776736 +DA:36,2776736 +DA:39,10490 +DA:43,2670 +DA:44,581344 +DA:45,581344 +DA:47,581344 +DA:52,10490 +DA:53,10490 +DA:54,10490 +DA:55,2776736 +DA:56,2776736 +DA:58,2776736 +DA:61,10490 +DA:65,208 +DA:66,204096 +DA:67,204096 +DA:68,204096 +DA:70,204096 +DA:75,10490 +DA:76,10490 +DA:77,2776736 +DA:78,2776736 +DA:79,2776736 +DA:81,2776736 +DA:84,10490 +DA:88,6931 +DA:89,1879128 +DA:90,1879128 +DA:92,1879128 +DA:93,1879128 +DA:95,1879128 +DA:100,10490 +DA:101,10490 +DA:102,2776736 +DA:103,2776736 +DA:105,2776736 +DA:106,2776736 +DA:108,2776736 +DA:111,10490 +DA:114,1 +DA:122,1 +DA:130,1 +DA:132,325 +DA:133,325 +DA:134,0 +DA:135,0 +DA:137,0 +DA:140,325 +DA:141,0 +DA:143,325 +DA:144,325 +DA:145,325 +DA:146,325 +DA:148,325 +DA:150,325 +DA:151,10490 +DA:153,10490 +DA:155,10490 +DA:156,52450 +DA:157,52450 +DA:158,35370 +DA:159,35370 +DA:164,10490 +DA:165,10490 +DA:166,10490 +DA:167,10490 +DA:168,10490 +DA:170,325 +LF:84 +LH:80 +BRDA:23,0,0,104484 +BRDA:23,0,1,2548 +BRDA:33,1,0,2734776 +BRDA:33,1,1,41960 +BRDA:44,2,0,581344 +BRDA:44,2,1,0 +BRDA:55,3,0,2734120 +BRDA:55,3,1,42616 +BRDA:66,4,0,203264 +BRDA:66,4,1,832 +BRDA:67,5,0,204096 +BRDA:67,5,1,0 +BRDA:77,6,0,2734776 +BRDA:77,6,1,41960 +BRDA:78,7,0,2734120 +BRDA:78,7,1,42616 +BRDA:89,8,0,1851404 +BRDA:89,8,1,27724 +BRDA:90,9,0,1879128 +BRDA:90,9,1,0 +BRDA:92,10,0,1851404 +BRDA:92,10,1,27724 +BRDA:92,11,0,1879128 +BRDA:92,11,1,1879128 +BRDA:102,12,0,2734776 +BRDA:102,12,1,41960 +BRDA:103,13,0,2734120 +BRDA:103,13,1,42616 +BRDA:105,14,0,2693460 +BRDA:105,14,1,83276 +BRDA:105,15,0,2776736 +BRDA:105,15,1,2734120 +BRDA:132,16,0,325 +BRDA:132,16,1,0 +BRDA:132,17,0,325 +BRDA:132,17,1,1 +BRDA:134,18,0,0 +BRDA:134,18,1,0 +BRDA:140,19,0,0 +BRDA:140,19,1,325 +BRDA:151,20,0,10490 +BRDA:151,20,1,0 +BRDA:157,21,0,35370 +BRDA:157,21,1,17080 +BRF:44 +BRH:36 +end_of_record +TN: +SF:lib\filter-parse-async.js +FN:7,(anonymous_0) +FN:14,(anonymous_1) +FN:17,(anonymous_2) +FNF:3 +FNH:3 +FNDA:176,(anonymous_0) +FNDA:9057,(anonymous_1) +FNDA:173,(anonymous_2) +DA:3,1 +DA:4,1 +DA:5,1 +DA:7,1 +DA:8,176 +DA:10,176 +DA:11,176 +DA:12,176 +DA:15,9057 +DA:18,173 +DA:22,176 +DA:24,1 +LF:12 +LH:12 +BRF:0 +BRH:0 +end_of_record +TN: +SF:lib\filter-parse-sync.js +FN:6,(anonymous_0) +FN:11,(anonymous_1) +FN:14,(anonymous_2) +FNF:3 +FNH:3 +FNDA:162,(anonymous_0) +FNDA:6337,(anonymous_1) +FNDA:162,(anonymous_2) +DA:3,1 +DA:4,1 +DA:6,1 +DA:7,162 +DA:8,162 +DA:9,162 +DA:12,6337 +DA:17,162 +DA:18,162 +DA:20,162 +LF:10 +LH:10 +BRF:0 +BRH:0 +end_of_record +TN: +SF:lib\filter-parse.js +FN:6,getByteWidth +FN:14,(anonymous_1) +FN:57,(anonymous_2) +FN:64,(anonymous_3) +FN:79,(anonymous_4) +FN:93,(anonymous_5) +FN:111,(anonymous_6) +FN:130,(anonymous_7) +FNF:8 +FNH:8 +FNDA:742,getByteWidth +FNDA:338,(anonymous_1) +FNDA:338,(anonymous_2) +FNDA:1939,(anonymous_3) +FNDA:800,(anonymous_4) +FNDA:172,(anonymous_5) +FNDA:4165,(anonymous_6) +FNDA:15394,(anonymous_7) +DA:3,1 +DA:4,1 +DA:7,742 +DA:8,742 +DA:9,531 +DA:11,742 +DA:14,1 +DA:15,338 +DA:16,338 +DA:17,338 +DA:18,338 +DA:19,338 +DA:21,338 +DA:22,338 +DA:23,338 +DA:25,338 +DA:26,338 +DA:27,338 +DA:28,72 +DA:29,72 +DA:30,476 +DA:37,266 +DA:48,338 +DA:49,127 +DA:50,211 +DA:51,66 +DA:53,145 +DA:57,1 +DA:58,338 +DA:64,1 +DA:69,1939 +DA:70,1939 +DA:72,1939 +DA:73,3563504 +DA:74,3563504 +DA:75,3563504 +DA:79,1 +DA:84,800 +DA:86,800 +DA:87,330256 +DA:88,330256 +DA:89,330256 +DA:93,1 +DA:98,172 +DA:99,172 +DA:100,172 +DA:102,172 +DA:103,9952 +DA:104,9952 +DA:105,9952 +DA:106,9952 +DA:107,9952 +DA:111,1 +DA:116,4165 +DA:117,4165 +DA:118,4165 +DA:120,4165 +DA:121,1152544 +DA:122,1152544 +DA:123,1152544 +DA:124,1152544 +DA:125,1152544 +DA:126,1152544 +DA:130,1 +DA:131,15394 +DA:133,15394 +DA:134,15394 +DA:136,15394 +DA:137,8318 +DA:139,7076 +DA:141,7076 +DA:143,1939 +DA:144,1939 +DA:146,800 +DA:147,800 +DA:149,172 +DA:150,172 +DA:152,4165 +DA:153,4165 +DA:155,0 +DA:159,15394 +DA:161,15394 +DA:162,15394 +DA:163,739 +DA:164,739 +DA:165,739 +DA:167,14655 +DA:170,15394 +DA:172,15059 +DA:174,335 +DA:175,335 +LF:91 +LH:90 +BRDA:8,0,0,531 +BRDA:8,0,1,211 +BRDA:27,1,0,72 +BRDA:27,1,1,266 +BRDA:48,2,0,127 +BRDA:48,2,1,211 +BRDA:50,3,0,66 +BRDA:50,3,1,145 +BRDA:74,4,0,3557696 +BRDA:74,4,1,5808 +BRDA:88,5,0,330000 +BRDA:88,5,1,256 +BRDA:104,6,0,9536 +BRDA:104,6,1,416 +BRDA:105,7,0,9554 +BRDA:105,7,1,398 +BRDA:122,8,0,1152288 +BRDA:122,8,1,256 +BRDA:123,9,0,1137296 +BRDA:123,9,1,15248 +BRDA:124,10,0,1137048 +BRDA:124,10,1,15496 +BRDA:124,11,0,1152544 +BRDA:124,11,1,1137296 +BRDA:136,12,0,8318 +BRDA:136,12,1,7076 +BRDA:141,13,0,1939 +BRDA:141,13,1,800 +BRDA:141,13,2,172 +BRDA:141,13,3,4165 +BRDA:141,13,4,0 +BRDA:162,14,0,739 +BRDA:162,14,1,14655 +BRDA:170,15,0,15059 +BRDA:170,15,1,335 +BRF:35 +BRH:34 +end_of_record +TN: +SF:lib\format-normaliser.js +FN:3,dePalette +FN:22,replaceTransparentColor +FN:49,scaleDepth +FN:66,(anonymous_3) +FNF:4 +FNH:4 +FNDA:131,dePalette +FNDA:12,replaceTransparentColor +FNDA:106,scaleDepth +FNDA:335,(anonymous_3) +DA:4,131 +DA:6,131 +DA:7,4912 +DA:8,1418436 +DA:10,1418436 +DA:11,0 +DA:14,1418436 +DA:15,5673744 +DA:17,1418436 +DA:23,12 +DA:24,12 +DA:25,384 +DA:26,12288 +DA:28,12288 +DA:29,6144 +DA:30,2762 +DA:32,6144 +DA:37,2718 +DA:39,12288 +DA:40,5480 +DA:41,21920 +DA:44,12288 +DA:50,106 +DA:51,106 +DA:52,106 +DA:54,106 +DA:55,3392 +DA:56,108544 +DA:57,434176 +DA:61,108544 +DA:66,1 +DA:67,335 +DA:68,335 +DA:69,335 +DA:70,335 +DA:71,335 +DA:72,335 +DA:74,335 +DA:76,335 +DA:78,131 +DA:80,204 +DA:81,12 +DA:84,204 +DA:86,106 +DA:87,66 +DA:89,106 +DA:92,335 +LF:47 +LH:46 +BRDA:10,0,0,0 +BRDA:10,0,1,1418436 +BRDA:28,1,0,6144 +BRDA:28,1,1,6144 +BRDA:29,2,0,2762 +BRDA:29,2,1,3382 +BRDA:32,3,0,2718 +BRDA:32,3,1,3426 +BRDA:33,4,0,6144 +BRDA:33,4,1,2718 +BRDA:33,4,2,2718 +BRDA:39,5,0,5480 +BRDA:39,5,1,6808 +BRDA:76,6,0,131 +BRDA:76,6,1,204 +BRDA:80,7,0,12 +BRDA:80,7,1,192 +BRDA:84,8,0,106 +BRDA:84,8,1,98 +BRDA:86,9,0,66 +BRDA:86,9,1,40 +BRF:21 +BRH:20 +end_of_record +TN: +SF:lib\interlace.js +FN:52,(anonymous_0) +FN:83,(anonymous_1) +FN:84,(anonymous_2) +FNF:3 +FNH:3 +FNDA:144,(anonymous_0) +FNDA:72,(anonymous_1) +FNDA:324850,(anonymous_2) +DA:14,1 +DA:52,1 +DA:53,144 +DA:54,144 +DA:55,144 +DA:56,144 +DA:57,144 +DA:58,144 +DA:59,1008 +DA:60,1008 +DA:61,1008 +DA:62,1008 +DA:63,1556 +DA:64,672 +DA:66,884 +DA:69,1008 +DA:70,1360 +DA:71,552 +DA:73,808 +DA:76,1008 +DA:77,952 +DA:80,144 +DA:83,1 +DA:84,72 +DA:85,324850 +DA:87,324850 +DA:89,324850 +DA:91,324850 +DA:93,324850 +LF:29 +LH:29 +BRDA:63,0,0,672 +BRDA:63,0,1,884 +BRDA:70,1,0,552 +BRDA:70,1,1,808 +BRDA:76,2,0,952 +BRDA:76,2,1,56 +BRDA:76,3,0,1008 +BRDA:76,3,1,980 +BRF:8 +BRH:8 +end_of_record +TN: +SF:lib\packer-async.js +FN:8,(anonymous_0) +FN:20,(anonymous_1) +FN:36,(anonymous_2) +FN:43,(anonymous_3) +FNF:4 +FNH:4 +FNDA:353,(anonymous_0) +FNDA:325,(anonymous_1) +FNDA:652,(anonymous_2) +FNDA:325,(anonymous_3) +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:8,1 +DA:9,353 +DA:11,353 +DA:13,353 +DA:14,353 +DA:16,353 +DA:18,1 +DA:20,1 +DA:22,325 +DA:23,325 +DA:25,325 +DA:26,290 +DA:29,325 +DA:32,325 +DA:34,325 +DA:37,652 +DA:41,325 +DA:44,325 +DA:45,325 +DA:49,325 +LF:24 +LH:24 +BRDA:11,0,0,353 +BRDA:11,0,1,0 +BRDA:25,1,0,290 +BRDA:25,1,1,35 +BRF:4 +BRH:3 +end_of_record +TN: +SF:lib\packer-sync.js +FN:11,(anonymous_0) +FNF:1 +FNH:0 +FNDA:0,(anonymous_0) +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,0 +DA:8,1 +DA:9,1 +DA:11,1 +DA:12,0 +DA:13,0 +DA:18,0 +DA:20,0 +DA:22,0 +DA:25,0 +DA:28,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:41,0 +DA:45,0 +DA:47,0 +DA:48,0 +DA:50,0 +DA:53,0 +DA:55,0 +LF:24 +LH:6 +BRDA:5,0,0,0 +BRDA:5,0,1,1 +BRDA:12,1,0,0 +BRDA:12,1,1,0 +BRDA:18,2,0,0 +BRDA:18,2,1,0 +BRDA:30,3,0,0 +BRDA:30,3,1,0 +BRDA:47,4,0,0 +BRDA:47,4,1,0 +BRDA:47,5,0,0 +BRDA:47,5,1,0 +BRF:12 +BRH:1 +end_of_record +TN: +SF:lib\packer.js +FN:9,(anonymous_0) +FN:64,(anonymous_1) +FN:72,(anonymous_2) +FN:76,(anonymous_3) +FN:86,(anonymous_4) +FN:104,(anonymous_5) +FN:110,(anonymous_6) +FN:123,(anonymous_7) +FN:127,(anonymous_8) +FNF:9 +FNH:9 +FNDA:353,(anonymous_0) +FNDA:353,(anonymous_1) +FNDA:353,(anonymous_2) +FNDA:325,(anonymous_3) +FNDA:1592,(anonymous_4) +FNDA:290,(anonymous_5) +FNDA:325,(anonymous_6) +FNDA:652,(anonymous_7) +FNDA:325,(anonymous_8) +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:9,1 +DA:10,353 +DA:12,353 +DA:13,353 +DA:15,353 +DA:17,353 +DA:19,353 +DA:20,353 +DA:22,353 +DA:26,353 +DA:31,353 +DA:39,0 +DA:43,353 +DA:51,0 +DA:57,353 +DA:58,0 +DA:64,1 +DA:65,353 +DA:72,1 +DA:73,353 +DA:76,1 +DA:78,325 +DA:81,325 +DA:82,325 +DA:83,325 +DA:86,1 +DA:87,1592 +DA:88,1592 +DA:90,1592 +DA:91,1592 +DA:93,1592 +DA:94,1267 +DA:97,1592 +DA:101,1592 +DA:104,1 +DA:105,290 +DA:106,290 +DA:107,290 +DA:110,1 +DA:111,325 +DA:112,325 +DA:113,325 +DA:114,325 +DA:115,325 +DA:116,325 +DA:117,325 +DA:118,325 +DA:120,325 +DA:123,1 +DA:124,652 +DA:127,1 +DA:128,325 +LF:57 +LH:54 +BRDA:12,0,0,353 +BRDA:12,0,1,353 +BRDA:14,1,0,0 +BRDA:14,1,1,353 +BRDA:16,2,0,0 +BRDA:16,2,1,353 +BRDA:18,3,0,0 +BRDA:18,3,1,353 +BRDA:19,4,0,353 +BRDA:19,4,1,353 +BRDA:20,5,0,353 +BRDA:20,5,1,353 +BRDA:23,6,0,0 +BRDA:23,6,1,353 +BRDA:27,7,0,0 +BRDA:27,7,1,353 +BRDA:31,8,0,0 +BRDA:31,8,1,353 +BRDA:43,9,0,0 +BRDA:43,9,1,353 +BRDA:57,10,0,0 +BRDA:57,10,1,353 +BRDA:57,11,0,353 +BRDA:57,11,1,0 +BRDA:87,12,0,1267 +BRDA:87,12,1,325 +BRDA:93,13,0,1267 +BRDA:93,13,1,325 +BRF:28 +BRH:19 +end_of_record +TN: +SF:lib\paeth-predictor.js +FN:3,paethPredictor +FNF:1 +FNH:1 +FNDA:5808408,paethPredictor +DA:3,1 +DA:4,5808408 +DA:5,5808408 +DA:6,5808408 +DA:7,5808408 +DA:9,5808408 +DA:10,5156742 +DA:12,651666 +DA:13,539893 +DA:15,111773 +LF:10 +LH:10 +BRDA:9,0,0,5156742 +BRDA:9,0,1,651666 +BRDA:9,1,0,5808408 +BRDA:9,1,1,5231305 +BRDA:12,2,0,539893 +BRDA:12,2,1,111773 +BRF:6 +BRH:6 +end_of_record +TN: +SF:lib\parser-async.js +FN:11,(anonymous_0) +FN:33,(anonymous_1) +FN:49,(anonymous_2) +FN:55,(anonymous_3) +FN:79,(anonymous_4) +FN:89,(anonymous_5) +FN:109,(anonymous_6) +FN:116,(anonymous_7) +FN:120,(anonymous_8) +FN:124,(anonymous_9) +FN:128,(anonymous_10) +FN:134,(anonymous_11) +FN:147,(anonymous_12) +FNF:13 +FNH:11 +FNDA:353,(anonymous_0) +FNDA:14,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:741,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:487,(anonymous_5) +FNDA:176,(anonymous_6) +FNDA:7,(anonymous_7) +FNDA:77,(anonymous_8) +FNDA:15,(anonymous_9) +FNDA:174,(anonymous_10) +FNDA:173,(anonymous_11) +FNDA:173,(anonymous_12) +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:8,1 +DA:9,1 +DA:11,1 +DA:12,353 +DA:14,353 +DA:26,353 +DA:27,353 +DA:29,353 +DA:31,1 +DA:33,1 +DA:34,14 +DA:36,14 +DA:38,14 +DA:40,14 +DA:41,1 +DA:44,14 +DA:45,2 +DA:49,2 +DA:52,14 +DA:55,1 +DA:56,741 +DA:57,174 +DA:58,36 +DA:60,36 +DA:61,36 +DA:63,36 +DA:66,138 +DA:72,138 +DA:73,138 +DA:75,138 +DA:76,138 +DA:78,138 +DA:79,138 +DA:80,0 +DA:81,0 +DA:84,0 +DA:86,138 +DA:88,138 +DA:89,138 +DA:90,487 +DA:91,0 +DA:94,487 +DA:95,0 +DA:98,487 +DA:100,487 +DA:103,138 +DA:106,741 +DA:109,1 +DA:110,176 +DA:111,176 +DA:113,176 +DA:116,1 +DA:117,7 +DA:120,1 +DA:121,77 +DA:124,1 +DA:125,15 +DA:128,1 +DA:131,174 +DA:134,1 +DA:135,173 +DA:136,0 +DA:139,173 +DA:140,1 +DA:143,172 +DA:147,1 +DA:148,173 +DA:149,0 +DA:154,173 +DA:155,173 +DA:157,173 +DA:158,173 +DA:160,0 +DA:161,0 +DA:164,173 +LF:80 +LH:71 +BRDA:40,0,0,1 +BRDA:40,0,1,13 +BRDA:40,1,0,14 +BRDA:40,1,1,1 +BRDA:44,2,0,2 +BRDA:44,2,1,12 +BRDA:56,3,0,174 +BRDA:56,3,1,567 +BRDA:57,4,0,36 +BRDA:57,4,1,138 +BRDA:80,5,0,0 +BRDA:80,5,1,0 +BRDA:90,6,0,0 +BRDA:90,6,1,487 +BRDA:94,7,0,0 +BRDA:94,7,1,487 +BRDA:135,8,0,0 +BRDA:135,8,1,173 +BRDA:139,9,0,1 +BRDA:139,9,1,172 +BRDA:148,10,0,0 +BRDA:148,10,1,173 +BRF:22 +BRH:16 +end_of_record +TN: +SF:lib\parser-sync.js +FN:15,(anonymous_0) +FN:23,handleError +FN:28,handleMetaData +FN:32,handleTransColor +FN:36,handlePalette +FN:40,handleSimpleTransparency +FN:45,handleGamma +FN:50,handleInflateData +FNF:8 +FNH:8 +FNDA:176,(anonymous_0) +FNDA:13,handleError +FNDA:165,handleMetaData +FNDA:5,handleTransColor +FNDA:73,handlePalette +FNDA:12,handleSimpleTransparency +FNDA:147,handleGamma +FNDA:492,handleInflateData +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:7,0 +DA:9,1 +DA:10,1 +DA:11,1 +DA:12,1 +DA:13,1 +DA:15,1 +DA:16,176 +DA:17,0 +DA:24,13 +DA:29,165 +DA:33,5 +DA:37,73 +DA:41,12 +DA:46,147 +DA:49,176 +DA:51,492 +DA:54,176 +DA:56,176 +DA:67,176 +DA:68,176 +DA:70,176 +DA:71,13 +DA:75,163 +DA:76,163 +DA:79,163 +DA:80,36 +DA:83,127 +DA:84,127 +DA:85,127 +DA:90,162 +DA:92,162 +DA:93,0 +DA:96,162 +DA:97,162 +DA:99,162 +DA:100,162 +DA:102,162 +DA:104,162 +DA:105,162 +DA:107,162 +LF:45 +LH:42 +BRDA:6,0,0,0 +BRDA:6,0,1,1 +BRDA:16,1,0,0 +BRDA:16,1,1,176 +BRDA:70,2,0,13 +BRDA:70,2,1,163 +BRDA:79,3,0,36 +BRDA:79,3,1,127 +BRDA:92,4,0,0 +BRDA:92,4,1,162 +BRDA:92,5,0,162 +BRDA:92,5,1,162 +BRDA:105,6,0,162 +BRDA:105,6,1,17 +BRF:14 +BRH:11 +end_of_record +TN: +SF:lib\parser.js +FN:6,(anonymous_0) +FN:36,(anonymous_1) +FN:39,(anonymous_2) +FN:43,(anonymous_3) +FN:55,(anonymous_4) +FN:93,(anonymous_5) +FN:97,(anonymous_6) +FN:101,(anonymous_7) +FN:116,(anonymous_8) +FN:119,(anonymous_9) +FN:183,(anonymous_10) +FN:186,(anonymous_11) +FN:201,(anonymous_12) +FN:205,(anonymous_13) +FN:241,(anonymous_14) +FN:244,(anonymous_15) +FN:251,(anonymous_16) +FN:258,(anonymous_17) +FN:278,(anonymous_18) +FN:281,(anonymous_19) +FNF:20 +FNH:20 +FNDA:529,(anonymous_0) +FNDA:163,(anonymous_1) +FNDA:529,(anonymous_2) +FNDA:365,(anonymous_3) +FNDA:2461,(anonymous_4) +FNDA:256,(anonymous_5) +FNDA:2195,(anonymous_6) +FNDA:2195,(anonymous_7) +FNDA:351,(anonymous_8) +FNDA:351,(anonymous_9) +FNDA:135,(anonymous_10) +FNDA:135,(anonymous_11) +FNDA:27,(anonymous_12) +FNDA:27,(anonymous_13) +FNDA:296,(anonymous_14) +FNDA:296,(anonymous_15) +FNDA:1233,(anonymous_16) +FNDA:1233,(anonymous_17) +FNDA:336,(anonymous_18) +FNDA:336,(anonymous_19) +DA:3,1 +DA:4,1 +DA:6,1 +DA:7,529 +DA:8,529 +DA:10,529 +DA:11,529 +DA:12,529 +DA:15,529 +DA:16,529 +DA:18,529 +DA:19,529 +DA:20,529 +DA:21,529 +DA:22,529 +DA:23,529 +DA:24,529 +DA:26,529 +DA:27,529 +DA:28,529 +DA:29,529 +DA:30,529 +DA:31,529 +DA:32,529 +DA:33,529 +DA:34,529 +DA:35,529 +DA:36,529 +DA:39,1 +DA:40,529 +DA:43,1 +DA:44,365 +DA:46,365 +DA:47,2867 +DA:48,13 +DA:49,13 +DA:52,352 +DA:55,1 +DA:57,2461 +DA:60,2461 +DA:61,2461 +DA:62,2461 +DA:63,9844 +DA:69,2461 +DA:73,2461 +DA:74,0 +DA:75,0 +DA:78,2461 +DA:79,2461 +DA:81,2461 +DA:82,2205 +DA:85,256 +DA:86,0 +DA:87,0 +DA:90,256 +DA:93,1 +DA:94,256 +DA:97,1 +DA:98,2195 +DA:101,1 +DA:102,2195 +DA:103,2195 +DA:106,2195 +DA:107,4 +DA:108,4 +DA:111,2191 +DA:112,1855 +DA:116,1 +DA:117,351 +DA:119,1 +DA:120,351 +DA:122,351 +DA:123,351 +DA:124,351 +DA:125,351 +DA:126,351 +DA:127,351 +DA:128,351 +DA:135,351 +DA:142,6 +DA:143,6 +DA:145,345 +DA:146,4 +DA:147,4 +DA:149,341 +DA:150,0 +DA:151,0 +DA:153,341 +DA:154,0 +DA:155,0 +DA:157,341 +DA:158,0 +DA:159,0 +DA:162,341 +DA:164,341 +DA:166,341 +DA:168,341 +DA:180,341 +DA:183,1 +DA:184,135 +DA:186,1 +DA:187,135 +DA:189,135 +DA:192,135 +DA:193,7350 +DA:196,135 +DA:198,135 +DA:201,1 +DA:202,27 +DA:203,27 +DA:205,1 +DA:206,27 +DA:209,27 +DA:210,15 +DA:211,0 +DA:212,0 +DA:214,15 +DA:215,0 +DA:216,0 +DA:218,15 +DA:219,529 +DA:221,15 +DA:226,27 +DA:228,6 +DA:230,27 +DA:231,6 +DA:238,27 +DA:241,1 +DA:242,296 +DA:244,1 +DA:245,296 +DA:246,296 +DA:248,296 +DA:251,1 +DA:252,1233 +DA:253,337 +DA:254,337 +DA:256,1233 +DA:258,1 +DA:259,1233 +DA:261,1233 +DA:265,0 +DA:268,1233 +DA:269,1233 +DA:271,1233 +DA:272,173 +DA:274,1060 +DA:278,1 +DA:279,336 +DA:281,1 +DA:282,336 +DA:284,336 +DA:285,336 +DA:287,336 +DA:288,173 +LF:155 +LH:140 +BRDA:36,0,0,529 +BRDA:36,0,1,176 +BRDA:47,1,0,13 +BRDA:47,1,1,2854 +BRDA:73,2,0,0 +BRDA:73,2,1,2461 +BRDA:73,3,0,2461 +BRDA:73,3,1,351 +BRDA:81,4,0,2205 +BRDA:81,4,1,256 +BRDA:85,5,0,0 +BRDA:85,5,1,256 +BRDA:106,6,0,4 +BRDA:106,6,1,2191 +BRDA:106,7,0,2195 +BRDA:106,7,1,2195 +BRDA:111,8,0,1855 +BRDA:111,8,1,336 +BRDA:135,9,0,6 +BRDA:135,9,1,345 +BRDA:136,10,0,351 +BRDA:136,10,1,219 +BRDA:136,10,2,132 +BRDA:136,10,3,101 +BRDA:136,10,4,72 +BRDA:145,11,0,4 +BRDA:145,11,1,341 +BRDA:149,12,0,0 +BRDA:149,12,1,341 +BRDA:153,13,0,0 +BRDA:153,13,1,341 +BRDA:157,14,0,0 +BRDA:157,14,1,341 +BRDA:157,15,0,341 +BRDA:157,15,1,72 +BRDA:209,16,0,15 +BRDA:209,16,1,12 +BRDA:210,17,0,0 +BRDA:210,17,1,15 +BRDA:214,18,0,0 +BRDA:214,18,1,15 +BRDA:226,19,0,6 +BRDA:226,19,1,21 +BRDA:230,20,0,6 +BRDA:230,20,1,21 +BRDA:252,21,0,337 +BRDA:252,21,1,896 +BRDA:261,22,0,0 +BRDA:261,22,1,1233 +BRDA:262,23,0,1233 +BRDA:262,23,1,131 +BRDA:271,24,0,173 +BRDA:271,24,1,1060 +BRDA:287,25,0,173 +BRDA:287,25,1,163 +BRF:55 +BRH:47 +end_of_record +TN: +SF:lib\png-sync.js +FN:6,(anonymous_0) +FN:10,(anonymous_1) +FNF:2 +FNH:1 +FNDA:176,(anonymous_0) +FNDA:0,(anonymous_1) +DA:3,1 +DA:4,1 +DA:6,1 +DA:7,176 +DA:10,1 +DA:11,0 +LF:6 +LH:5 +BRDA:7,0,0,176 +BRDA:7,0,1,176 +BRF:2 +BRH:2 +end_of_record +TN: +SF:lib\png.js +FN:9,(anonymous_0) +FN:38,(anonymous_1) +FN:54,(anonymous_2) +FN:61,(anonymous_3) +FN:69,(anonymous_4) +FN:73,(anonymous_5) +FN:80,(anonymous_6) +FN:94,(anonymous_7) +FN:99,(anonymous_8) +FN:103,(anonymous_9) +FN:110,(anonymous_10) +FN:114,(anonymous_11) +FN:120,(anonymous_12) +FN:160,(anonymous_13) +FN:175,(anonymous_14) +FN:192,(anonymous_15) +FNF:16 +FNH:9 +FNDA:353,(anonymous_0) +FNDA:173,(anonymous_1) +FNDA:325,(anonymous_2) +FNDA:325,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:412,(anonymous_7) +FNDA:175,(anonymous_8) +FNDA:174,(anonymous_9) +FNDA:149,(anonymous_10) +FNDA:378,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:0,(anonymous_15) +DA:3,1 +DA:4,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:9,1 +DA:10,353 +DA:12,353 +DA:15,353 +DA:16,353 +DA:18,353 +DA:23,353 +DA:24,0 +DA:27,353 +DA:28,353 +DA:30,353 +DA:32,353 +DA:33,353 +DA:34,353 +DA:35,353 +DA:36,353 +DA:39,173 +DA:40,173 +DA:44,353 +DA:45,353 +DA:46,353 +DA:47,353 +DA:48,353 +DA:50,1 +DA:52,1 +DA:54,1 +DA:55,325 +DA:56,0 +DA:57,0 +DA:60,325 +DA:62,325 +DA:66,325 +DA:69,1 +DA:70,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:86,0 +DA:87,0 +DA:90,0 +DA:91,0 +DA:94,1 +DA:95,412 +DA:96,412 +DA:99,1 +DA:100,175 +DA:103,1 +DA:104,174 +DA:105,174 +DA:107,174 +DA:110,1 +DA:111,149 +DA:114,1 +DA:115,378 +DA:116,0 +DA:120,1 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:132,0 +DA:138,0 +DA:141,0 +DA:147,0 +DA:150,0 +DA:151,0 +DA:160,1 +DA:171,0 +DA:172,0 +DA:175,1 +DA:176,0 +DA:177,0 +DA:178,0 +DA:179,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:188,0 +DA:192,1 +DA:193,0 +LF:92 +LH:52 +BRDA:12,0,0,353 +BRDA:12,0,1,348 +BRDA:19,1,0,1 +BRDA:19,1,1,352 +BRDA:19,2,0,353 +BRDA:19,2,1,1 +BRDA:23,3,0,0 +BRDA:23,3,1,353 +BRDA:23,4,0,353 +BRDA:23,4,1,0 +BRDA:55,5,0,0 +BRDA:55,5,1,325 +BRDA:55,6,0,325 +BRDA:55,6,1,325 +BRDA:70,7,0,0 +BRDA:70,7,1,0 +BRDA:115,8,0,0 +BRDA:115,8,1,378 +BRDA:115,9,0,378 +BRDA:115,9,1,378 +BRDA:132,10,0,0 +BRDA:132,10,1,0 +BRDA:133,11,0,0 +BRDA:133,11,1,0 +BRDA:133,11,2,0 +BRDA:133,11,3,0 +BRDA:141,12,0,0 +BRDA:141,12,1,0 +BRDA:142,13,0,0 +BRDA:142,13,1,0 +BRDA:142,13,2,0 +BRDA:142,13,3,0 +BRDA:176,14,0,0 +BRDA:176,14,1,0 +BRF:34 +BRH:14 +end_of_record +TN: +SF:lib\sync-inflate.js +FN:9,Inflate +FN:29,createInflate +FN:33,_close +FN:47,(anonymous_3) +FN:63,(anonymous_4) +FN:67,handleChunk +FN:145,zlibBufferSync +FN:161,inflateSync +FNF:8 +FNH:7 +FNDA:127,Inflate +FNDA:0,createInflate +FNDA:126,_close +FNDA:127,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:126,handleChunk +FNDA:127,zlibBufferSync +FNDA:127,inflateSync +DA:3,1 +DA:4,1 +DA:5,1 +DA:7,1 +DA:10,127 +DA:11,0 +DA:14,127 +DA:15,9 +DA:18,127 +DA:21,127 +DA:22,127 +DA:24,127 +DA:25,127 +DA:30,0 +DA:34,126 +DA:35,0 +DA:39,126 +DA:40,0 +DA:43,126 +DA:44,126 +DA:47,1 +DA:48,127 +DA:49,0 +DA:52,127 +DA:54,127 +DA:55,127 +DA:56,127 +DA:57,127 +DA:59,127 +DA:60,127 +DA:63,127 +DA:64,1 +DA:68,126 +DA:69,0 +DA:72,126 +DA:73,126 +DA:75,126 +DA:76,126 +DA:77,126 +DA:79,126 +DA:80,9 +DA:83,126 +DA:84,126 +DA:85,126 +DA:87,126 +DA:88,126 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:102,0 +DA:105,0 +DA:108,127 +DA:110,127 +DA:111,127 +DA:121,127 +DA:124,127 +DA:125,1 +DA:128,126 +DA:129,0 +DA:130,0 +DA:137,126 +DA:138,126 +DA:140,126 +DA:143,1 +DA:146,127 +DA:147,0 +DA:149,127 +DA:150,0 +DA:153,127 +DA:154,127 +DA:155,0 +DA:158,127 +DA:162,127 +DA:165,1 +DA:166,1 +DA:167,1 +DA:168,1 +LF:81 +LH:61 +BRDA:10,0,0,0 +BRDA:10,0,1,127 +BRDA:14,1,0,9 +BRDA:14,1,1,118 +BRDA:14,2,0,127 +BRDA:14,2,1,127 +BRDA:21,3,0,127 +BRDA:21,3,1,0 +BRDA:22,4,0,127 +BRDA:22,4,1,127 +BRDA:24,5,0,127 +BRDA:24,5,1,0 +BRDA:24,6,0,127 +BRDA:24,6,1,127 +BRDA:34,7,0,0 +BRDA:34,7,1,126 +BRDA:39,8,0,0 +BRDA:39,8,1,126 +BRDA:48,9,0,0 +BRDA:48,9,1,127 +BRDA:54,10,0,127 +BRDA:54,10,1,127 +BRDA:68,11,0,0 +BRDA:68,11,1,126 +BRDA:75,12,0,126 +BRDA:75,12,1,0 +BRDA:79,13,0,9 +BRDA:79,13,1,117 +BRDA:87,14,0,126 +BRDA:87,14,1,0 +BRDA:92,15,0,0 +BRDA:92,15,1,0 +BRDA:92,16,0,0 +BRDA:92,16,1,0 +BRDA:98,17,0,0 +BRDA:98,17,1,0 +BRDA:122,18,0,127 +BRDA:122,18,1,126 +BRDA:121,19,0,127 +BRDA:121,19,1,127 +BRDA:124,20,0,1 +BRDA:124,20,1,126 +BRDA:128,21,0,0 +BRDA:128,21,1,126 +BRDA:146,22,0,0 +BRDA:146,22,1,127 +BRDA:149,23,0,0 +BRDA:149,23,1,127 +BRDA:154,24,0,0 +BRDA:154,24,1,127 +BRF:50 +BRH:31 +end_of_record +TN: +SF:lib\sync-reader.js +FN:3,(anonymous_0) +FN:8,(anonymous_1) +FN:16,(anonymous_2) +FNF:3 +FNH:3 +FNDA:338,(anonymous_0) +FNDA:9900,(anonymous_1) +FNDA:338,(anonymous_2) +DA:3,1 +DA:4,338 +DA:5,338 +DA:8,1 +DA:9,9900 +DA:16,1 +DA:18,338 +DA:19,9900 +DA:21,9900 +DA:26,9900 +DA:28,9900 +DA:30,9900 +DA:32,9900 +DA:34,0 +DA:38,338 +DA:39,0 +DA:42,338 +DA:43,13 +LF:18 +LH:16 +BRDA:18,0,0,10238 +BRDA:18,0,1,9900 +BRDA:21,1,0,9900 +BRDA:21,1,1,0 +BRDA:22,2,0,9900 +BRDA:22,2,1,9900 +BRDA:22,2,2,0 +BRDA:38,3,0,0 +BRDA:38,3,1,338 +BRDA:42,4,0,13 +BRDA:42,4,1,325 +BRF:11 +BRH:8 +end_of_record diff --git a/node_modules/pngjs/lib/bitmapper.js b/node_modules/pngjs/lib/bitmapper.js new file mode 100644 index 0000000..18378a0 --- /dev/null +++ b/node_modules/pngjs/lib/bitmapper.js @@ -0,0 +1,267 @@ +"use strict"; + +let interlaceUtils = require("./interlace"); + +let pixelBppMapper = [ + // 0 - dummy entry + function () {}, + + // 1 - L + // 0: 0, 1: 0, 2: 0, 3: 0xff + function (pxData, data, pxPos, rawPos) { + if (rawPos === data.length) { + throw new Error("Ran out of data"); + } + + let pixel = data[rawPos]; + pxData[pxPos] = pixel; + pxData[pxPos + 1] = pixel; + pxData[pxPos + 2] = pixel; + pxData[pxPos + 3] = 0xff; + }, + + // 2 - LA + // 0: 0, 1: 0, 2: 0, 3: 1 + function (pxData, data, pxPos, rawPos) { + if (rawPos + 1 >= data.length) { + throw new Error("Ran out of data"); + } + + let pixel = data[rawPos]; + pxData[pxPos] = pixel; + pxData[pxPos + 1] = pixel; + pxData[pxPos + 2] = pixel; + pxData[pxPos + 3] = data[rawPos + 1]; + }, + + // 3 - RGB + // 0: 0, 1: 1, 2: 2, 3: 0xff + function (pxData, data, pxPos, rawPos) { + if (rawPos + 2 >= data.length) { + throw new Error("Ran out of data"); + } + + pxData[pxPos] = data[rawPos]; + pxData[pxPos + 1] = data[rawPos + 1]; + pxData[pxPos + 2] = data[rawPos + 2]; + pxData[pxPos + 3] = 0xff; + }, + + // 4 - RGBA + // 0: 0, 1: 1, 2: 2, 3: 3 + function (pxData, data, pxPos, rawPos) { + if (rawPos + 3 >= data.length) { + throw new Error("Ran out of data"); + } + + pxData[pxPos] = data[rawPos]; + pxData[pxPos + 1] = data[rawPos + 1]; + pxData[pxPos + 2] = data[rawPos + 2]; + pxData[pxPos + 3] = data[rawPos + 3]; + }, +]; + +let pixelBppCustomMapper = [ + // 0 - dummy entry + function () {}, + + // 1 - L + // 0: 0, 1: 0, 2: 0, 3: 0xff + function (pxData, pixelData, pxPos, maxBit) { + let pixel = pixelData[0]; + pxData[pxPos] = pixel; + pxData[pxPos + 1] = pixel; + pxData[pxPos + 2] = pixel; + pxData[pxPos + 3] = maxBit; + }, + + // 2 - LA + // 0: 0, 1: 0, 2: 0, 3: 1 + function (pxData, pixelData, pxPos) { + let pixel = pixelData[0]; + pxData[pxPos] = pixel; + pxData[pxPos + 1] = pixel; + pxData[pxPos + 2] = pixel; + pxData[pxPos + 3] = pixelData[1]; + }, + + // 3 - RGB + // 0: 0, 1: 1, 2: 2, 3: 0xff + function (pxData, pixelData, pxPos, maxBit) { + pxData[pxPos] = pixelData[0]; + pxData[pxPos + 1] = pixelData[1]; + pxData[pxPos + 2] = pixelData[2]; + pxData[pxPos + 3] = maxBit; + }, + + // 4 - RGBA + // 0: 0, 1: 1, 2: 2, 3: 3 + function (pxData, pixelData, pxPos) { + pxData[pxPos] = pixelData[0]; + pxData[pxPos + 1] = pixelData[1]; + pxData[pxPos + 2] = pixelData[2]; + pxData[pxPos + 3] = pixelData[3]; + }, +]; + +function bitRetriever(data, depth) { + let leftOver = []; + let i = 0; + + function split() { + if (i === data.length) { + throw new Error("Ran out of data"); + } + let byte = data[i]; + i++; + let byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1; + switch (depth) { + default: + throw new Error("unrecognised depth"); + case 16: + byte2 = data[i]; + i++; + leftOver.push((byte << 8) + byte2); + break; + case 4: + byte2 = byte & 0x0f; + byte1 = byte >> 4; + leftOver.push(byte1, byte2); + break; + case 2: + byte4 = byte & 3; + byte3 = (byte >> 2) & 3; + byte2 = (byte >> 4) & 3; + byte1 = (byte >> 6) & 3; + leftOver.push(byte1, byte2, byte3, byte4); + break; + case 1: + byte8 = byte & 1; + byte7 = (byte >> 1) & 1; + byte6 = (byte >> 2) & 1; + byte5 = (byte >> 3) & 1; + byte4 = (byte >> 4) & 1; + byte3 = (byte >> 5) & 1; + byte2 = (byte >> 6) & 1; + byte1 = (byte >> 7) & 1; + leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8); + break; + } + } + + return { + get: function (count) { + while (leftOver.length < count) { + split(); + } + let returner = leftOver.slice(0, count); + leftOver = leftOver.slice(count); + return returner; + }, + resetAfterLine: function () { + leftOver.length = 0; + }, + end: function () { + if (i !== data.length) { + throw new Error("extra data found"); + } + }, + }; +} + +function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) { + // eslint-disable-line max-params + let imageWidth = image.width; + let imageHeight = image.height; + let imagePass = image.index; + for (let y = 0; y < imageHeight; y++) { + for (let x = 0; x < imageWidth; x++) { + let pxPos = getPxPos(x, y, imagePass); + pixelBppMapper[bpp](pxData, data, pxPos, rawPos); + rawPos += bpp; //eslint-disable-line no-param-reassign + } + } + return rawPos; +} + +function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) { + // eslint-disable-line max-params + let imageWidth = image.width; + let imageHeight = image.height; + let imagePass = image.index; + for (let y = 0; y < imageHeight; y++) { + for (let x = 0; x < imageWidth; x++) { + let pixelData = bits.get(bpp); + let pxPos = getPxPos(x, y, imagePass); + pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit); + } + bits.resetAfterLine(); + } +} + +exports.dataToBitMap = function (data, bitmapInfo) { + let width = bitmapInfo.width; + let height = bitmapInfo.height; + let depth = bitmapInfo.depth; + let bpp = bitmapInfo.bpp; + let interlace = bitmapInfo.interlace; + let bits; + + if (depth !== 8) { + bits = bitRetriever(data, depth); + } + let pxData; + if (depth <= 8) { + pxData = Buffer.alloc(width * height * 4); + } else { + pxData = new Uint16Array(width * height * 4); + } + let maxBit = Math.pow(2, depth) - 1; + let rawPos = 0; + let images; + let getPxPos; + + if (interlace) { + images = interlaceUtils.getImagePasses(width, height); + getPxPos = interlaceUtils.getInterlaceIterator(width, height); + } else { + let nonInterlacedPxPos = 0; + getPxPos = function () { + let returner = nonInterlacedPxPos; + nonInterlacedPxPos += 4; + return returner; + }; + images = [{ width: width, height: height }]; + } + + for (let imageIndex = 0; imageIndex < images.length; imageIndex++) { + if (depth === 8) { + rawPos = mapImage8Bit( + images[imageIndex], + pxData, + getPxPos, + bpp, + data, + rawPos + ); + } else { + mapImageCustomBit( + images[imageIndex], + pxData, + getPxPos, + bpp, + bits, + maxBit + ); + } + } + if (depth === 8) { + if (rawPos !== data.length) { + throw new Error("extra data found"); + } + } else { + bits.end(); + } + + return pxData; +}; diff --git a/node_modules/pngjs/lib/bitpacker.js b/node_modules/pngjs/lib/bitpacker.js new file mode 100644 index 0000000..d7a4e65 --- /dev/null +++ b/node_modules/pngjs/lib/bitpacker.js @@ -0,0 +1,158 @@ +"use strict"; + +let constants = require("./constants"); + +module.exports = function (dataIn, width, height, options) { + let outHasAlpha = + [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf( + options.colorType + ) !== -1; + if (options.colorType === options.inputColorType) { + let bigEndian = (function () { + let buffer = new ArrayBuffer(2); + new DataView(buffer).setInt16(0, 256, true /* littleEndian */); + // Int16Array uses the platform's endianness. + return new Int16Array(buffer)[0] !== 256; + })(); + // If no need to convert to grayscale and alpha is present/absent in both, take a fast route + if (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) { + return dataIn; + } + } + + // map to a UInt16 array if data is 16bit, fix endianness below + let data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer); + + let maxValue = 255; + let inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType]; + if (inBpp === 4 && !options.inputHasAlpha) { + inBpp = 3; + } + let outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType]; + if (options.bitDepth === 16) { + maxValue = 65535; + outBpp *= 2; + } + let outData = Buffer.alloc(width * height * outBpp); + + let inIndex = 0; + let outIndex = 0; + + let bgColor = options.bgColor || {}; + if (bgColor.red === undefined) { + bgColor.red = maxValue; + } + if (bgColor.green === undefined) { + bgColor.green = maxValue; + } + if (bgColor.blue === undefined) { + bgColor.blue = maxValue; + } + + function getRGBA() { + let red; + let green; + let blue; + let alpha = maxValue; + switch (options.inputColorType) { + case constants.COLORTYPE_COLOR_ALPHA: + alpha = data[inIndex + 3]; + red = data[inIndex]; + green = data[inIndex + 1]; + blue = data[inIndex + 2]; + break; + case constants.COLORTYPE_COLOR: + red = data[inIndex]; + green = data[inIndex + 1]; + blue = data[inIndex + 2]; + break; + case constants.COLORTYPE_ALPHA: + alpha = data[inIndex + 1]; + red = data[inIndex]; + green = red; + blue = red; + break; + case constants.COLORTYPE_GRAYSCALE: + red = data[inIndex]; + green = red; + blue = red; + break; + default: + throw new Error( + "input color type:" + + options.inputColorType + + " is not supported at present" + ); + } + + if (options.inputHasAlpha) { + if (!outHasAlpha) { + alpha /= maxValue; + red = Math.min( + Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0), + maxValue + ); + green = Math.min( + Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0), + maxValue + ); + blue = Math.min( + Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0), + maxValue + ); + } + } + return { red: red, green: green, blue: blue, alpha: alpha }; + } + + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + let rgba = getRGBA(data, inIndex); + + switch (options.colorType) { + case constants.COLORTYPE_COLOR_ALPHA: + case constants.COLORTYPE_COLOR: + if (options.bitDepth === 8) { + outData[outIndex] = rgba.red; + outData[outIndex + 1] = rgba.green; + outData[outIndex + 2] = rgba.blue; + if (outHasAlpha) { + outData[outIndex + 3] = rgba.alpha; + } + } else { + outData.writeUInt16BE(rgba.red, outIndex); + outData.writeUInt16BE(rgba.green, outIndex + 2); + outData.writeUInt16BE(rgba.blue, outIndex + 4); + if (outHasAlpha) { + outData.writeUInt16BE(rgba.alpha, outIndex + 6); + } + } + break; + case constants.COLORTYPE_ALPHA: + case constants.COLORTYPE_GRAYSCALE: { + // Convert to grayscale and alpha + let grayscale = (rgba.red + rgba.green + rgba.blue) / 3; + if (options.bitDepth === 8) { + outData[outIndex] = grayscale; + if (outHasAlpha) { + outData[outIndex + 1] = rgba.alpha; + } + } else { + outData.writeUInt16BE(grayscale, outIndex); + if (outHasAlpha) { + outData.writeUInt16BE(rgba.alpha, outIndex + 2); + } + } + break; + } + default: + throw new Error("unrecognised color Type " + options.colorType); + } + + inIndex += inBpp; + outIndex += outBpp; + } + } + + return outData; +}; diff --git a/node_modules/pngjs/lib/chunkstream.js b/node_modules/pngjs/lib/chunkstream.js new file mode 100644 index 0000000..95b46d4 --- /dev/null +++ b/node_modules/pngjs/lib/chunkstream.js @@ -0,0 +1,189 @@ +"use strict"; + +let util = require("util"); +let Stream = require("stream"); + +let ChunkStream = (module.exports = function () { + Stream.call(this); + + this._buffers = []; + this._buffered = 0; + + this._reads = []; + this._paused = false; + + this._encoding = "utf8"; + this.writable = true; +}); +util.inherits(ChunkStream, Stream); + +ChunkStream.prototype.read = function (length, callback) { + this._reads.push({ + length: Math.abs(length), // if length < 0 then at most this length + allowLess: length < 0, + func: callback, + }); + + process.nextTick( + function () { + this._process(); + + // its paused and there is not enought data then ask for more + if (this._paused && this._reads && this._reads.length > 0) { + this._paused = false; + + this.emit("drain"); + } + }.bind(this) + ); +}; + +ChunkStream.prototype.write = function (data, encoding) { + if (!this.writable) { + this.emit("error", new Error("Stream not writable")); + return false; + } + + let dataBuffer; + if (Buffer.isBuffer(data)) { + dataBuffer = data; + } else { + dataBuffer = Buffer.from(data, encoding || this._encoding); + } + + this._buffers.push(dataBuffer); + this._buffered += dataBuffer.length; + + this._process(); + + // ok if there are no more read requests + if (this._reads && this._reads.length === 0) { + this._paused = true; + } + + return this.writable && !this._paused; +}; + +ChunkStream.prototype.end = function (data, encoding) { + if (data) { + this.write(data, encoding); + } + + this.writable = false; + + // already destroyed + if (!this._buffers) { + return; + } + + // enqueue or handle end + if (this._buffers.length === 0) { + this._end(); + } else { + this._buffers.push(null); + this._process(); + } +}; + +ChunkStream.prototype.destroySoon = ChunkStream.prototype.end; + +ChunkStream.prototype._end = function () { + if (this._reads.length > 0) { + this.emit("error", new Error("Unexpected end of input")); + } + + this.destroy(); +}; + +ChunkStream.prototype.destroy = function () { + if (!this._buffers) { + return; + } + + this.writable = false; + this._reads = null; + this._buffers = null; + + this.emit("close"); +}; + +ChunkStream.prototype._processReadAllowingLess = function (read) { + // ok there is any data so that we can satisfy this request + this._reads.shift(); // == read + + // first we need to peek into first buffer + let smallerBuf = this._buffers[0]; + + // ok there is more data than we need + if (smallerBuf.length > read.length) { + this._buffered -= read.length; + this._buffers[0] = smallerBuf.slice(read.length); + + read.func.call(this, smallerBuf.slice(0, read.length)); + } else { + // ok this is less than maximum length so use it all + this._buffered -= smallerBuf.length; + this._buffers.shift(); // == smallerBuf + + read.func.call(this, smallerBuf); + } +}; + +ChunkStream.prototype._processRead = function (read) { + this._reads.shift(); // == read + + let pos = 0; + let count = 0; + let data = Buffer.alloc(read.length); + + // create buffer for all data + while (pos < read.length) { + let buf = this._buffers[count++]; + let len = Math.min(buf.length, read.length - pos); + + buf.copy(data, pos, 0, len); + pos += len; + + // last buffer wasn't used all so just slice it and leave + if (len !== buf.length) { + this._buffers[--count] = buf.slice(len); + } + } + + // remove all used buffers + if (count > 0) { + this._buffers.splice(0, count); + } + + this._buffered -= read.length; + + read.func.call(this, data); +}; + +ChunkStream.prototype._process = function () { + try { + // as long as there is any data and read requests + while (this._buffered > 0 && this._reads && this._reads.length > 0) { + let read = this._reads[0]; + + // read any data (but no more than length) + if (read.allowLess) { + this._processReadAllowingLess(read); + } else if (this._buffered >= read.length) { + // ok we can meet some expectations + + this._processRead(read); + } else { + // not enought data to satisfy first request in queue + // so we need to wait for more + break; + } + } + + if (this._buffers && !this.writable) { + this._end(); + } + } catch (ex) { + this.emit("error", ex); + } +}; diff --git a/node_modules/pngjs/lib/constants.js b/node_modules/pngjs/lib/constants.js new file mode 100644 index 0000000..21fdad6 --- /dev/null +++ b/node_modules/pngjs/lib/constants.js @@ -0,0 +1,32 @@ +"use strict"; + +module.exports = { + PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], + + TYPE_IHDR: 0x49484452, + TYPE_IEND: 0x49454e44, + TYPE_IDAT: 0x49444154, + TYPE_PLTE: 0x504c5445, + TYPE_tRNS: 0x74524e53, // eslint-disable-line camelcase + TYPE_gAMA: 0x67414d41, // eslint-disable-line camelcase + + // color-type bits + COLORTYPE_GRAYSCALE: 0, + COLORTYPE_PALETTE: 1, + COLORTYPE_COLOR: 2, + COLORTYPE_ALPHA: 4, // e.g. grayscale and alpha + + // color-type combinations + COLORTYPE_PALETTE_COLOR: 3, + COLORTYPE_COLOR_ALPHA: 6, + + COLORTYPE_TO_BPP_MAP: { + 0: 1, + 2: 3, + 3: 1, + 4: 2, + 6: 4, + }, + + GAMMA_DIVISION: 100000, +}; diff --git a/node_modules/pngjs/lib/crc.js b/node_modules/pngjs/lib/crc.js new file mode 100644 index 0000000..950ec8a --- /dev/null +++ b/node_modules/pngjs/lib/crc.js @@ -0,0 +1,40 @@ +"use strict"; + +let crcTable = []; + +(function () { + for (let i = 0; i < 256; i++) { + let currentCrc = i; + for (let j = 0; j < 8; j++) { + if (currentCrc & 1) { + currentCrc = 0xedb88320 ^ (currentCrc >>> 1); + } else { + currentCrc = currentCrc >>> 1; + } + } + crcTable[i] = currentCrc; + } +})(); + +let CrcCalculator = (module.exports = function () { + this._crc = -1; +}); + +CrcCalculator.prototype.write = function (data) { + for (let i = 0; i < data.length; i++) { + this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8); + } + return true; +}; + +CrcCalculator.prototype.crc32 = function () { + return this._crc ^ -1; +}; + +CrcCalculator.crc32 = function (buf) { + let crc = -1; + for (let i = 0; i < buf.length; i++) { + crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8); + } + return crc ^ -1; +}; diff --git a/node_modules/pngjs/lib/filter-pack.js b/node_modules/pngjs/lib/filter-pack.js new file mode 100644 index 0000000..32c85c4 --- /dev/null +++ b/node_modules/pngjs/lib/filter-pack.js @@ -0,0 +1,171 @@ +"use strict"; + +let paethPredictor = require("./paeth-predictor"); + +function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) { + for (let x = 0; x < byteWidth; x++) { + rawData[rawPos + x] = pxData[pxPos + x]; + } +} + +function filterSumNone(pxData, pxPos, byteWidth) { + let sum = 0; + let length = pxPos + byteWidth; + + for (let i = pxPos; i < length; i++) { + sum += Math.abs(pxData[i]); + } + return sum; +} + +function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, bpp) { + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let val = pxData[pxPos + x] - left; + + rawData[rawPos + x] = val; + } +} + +function filterSumSub(pxData, pxPos, byteWidth, bpp) { + let sum = 0; + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let val = pxData[pxPos + x] - left; + + sum += Math.abs(val); + } + + return sum; +} + +function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) { + for (let x = 0; x < byteWidth; x++) { + let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; + let val = pxData[pxPos + x] - up; + + rawData[rawPos + x] = val; + } +} + +function filterSumUp(pxData, pxPos, byteWidth) { + let sum = 0; + let length = pxPos + byteWidth; + for (let x = pxPos; x < length; x++) { + let up = pxPos > 0 ? pxData[x - byteWidth] : 0; + let val = pxData[x] - up; + + sum += Math.abs(val); + } + + return sum; +} + +function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, bpp) { + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; + let val = pxData[pxPos + x] - ((left + up) >> 1); + + rawData[rawPos + x] = val; + } +} + +function filterSumAvg(pxData, pxPos, byteWidth, bpp) { + let sum = 0; + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; + let val = pxData[pxPos + x] - ((left + up) >> 1); + + sum += Math.abs(val); + } + + return sum; +} + +function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, bpp) { + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; + let upleft = + pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0; + let val = pxData[pxPos + x] - paethPredictor(left, up, upleft); + + rawData[rawPos + x] = val; + } +} + +function filterSumPaeth(pxData, pxPos, byteWidth, bpp) { + let sum = 0; + for (let x = 0; x < byteWidth; x++) { + let left = x >= bpp ? pxData[pxPos + x - bpp] : 0; + let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; + let upleft = + pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0; + let val = pxData[pxPos + x] - paethPredictor(left, up, upleft); + + sum += Math.abs(val); + } + + return sum; +} + +let filters = { + 0: filterNone, + 1: filterSub, + 2: filterUp, + 3: filterAvg, + 4: filterPaeth, +}; + +let filterSums = { + 0: filterSumNone, + 1: filterSumSub, + 2: filterSumUp, + 3: filterSumAvg, + 4: filterSumPaeth, +}; + +module.exports = function (pxData, width, height, options, bpp) { + let filterTypes; + if (!("filterType" in options) || options.filterType === -1) { + filterTypes = [0, 1, 2, 3, 4]; + } else if (typeof options.filterType === "number") { + filterTypes = [options.filterType]; + } else { + throw new Error("unrecognised filter types"); + } + + if (options.bitDepth === 16) { + bpp *= 2; + } + let byteWidth = width * bpp; + let rawPos = 0; + let pxPos = 0; + let rawData = Buffer.alloc((byteWidth + 1) * height); + + let sel = filterTypes[0]; + + for (let y = 0; y < height; y++) { + if (filterTypes.length > 1) { + // find best filter for this line (with lowest sum of values) + let min = Infinity; + + for (let i = 0; i < filterTypes.length; i++) { + let sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth, bpp); + if (sum < min) { + sel = filterTypes[i]; + min = sum; + } + } + } + + rawData[rawPos] = sel; + rawPos++; + filters[sel](pxData, pxPos, byteWidth, rawData, rawPos, bpp); + rawPos += byteWidth; + pxPos += byteWidth; + } + return rawData; +}; diff --git a/node_modules/pngjs/lib/filter-parse-async.js b/node_modules/pngjs/lib/filter-parse-async.js new file mode 100644 index 0000000..832b86c --- /dev/null +++ b/node_modules/pngjs/lib/filter-parse-async.js @@ -0,0 +1,24 @@ +"use strict"; + +let util = require("util"); +let ChunkStream = require("./chunkstream"); +let Filter = require("./filter-parse"); + +let FilterAsync = (module.exports = function (bitmapInfo) { + ChunkStream.call(this); + + let buffers = []; + let that = this; + this._filter = new Filter(bitmapInfo, { + read: this.read.bind(this), + write: function (buffer) { + buffers.push(buffer); + }, + complete: function () { + that.emit("complete", Buffer.concat(buffers)); + }, + }); + + this._filter.start(); +}); +util.inherits(FilterAsync, ChunkStream); diff --git a/node_modules/pngjs/lib/filter-parse-sync.js b/node_modules/pngjs/lib/filter-parse-sync.js new file mode 100644 index 0000000..6924d16 --- /dev/null +++ b/node_modules/pngjs/lib/filter-parse-sync.js @@ -0,0 +1,21 @@ +"use strict"; + +let SyncReader = require("./sync-reader"); +let Filter = require("./filter-parse"); + +exports.process = function (inBuffer, bitmapInfo) { + let outBuffers = []; + let reader = new SyncReader(inBuffer); + let filter = new Filter(bitmapInfo, { + read: reader.read.bind(reader), + write: function (bufferPart) { + outBuffers.push(bufferPart); + }, + complete: function () {}, + }); + + filter.start(); + reader.process(); + + return Buffer.concat(outBuffers); +}; diff --git a/node_modules/pngjs/lib/filter-parse.js b/node_modules/pngjs/lib/filter-parse.js new file mode 100644 index 0000000..3a32e5e --- /dev/null +++ b/node_modules/pngjs/lib/filter-parse.js @@ -0,0 +1,177 @@ +"use strict"; + +let interlaceUtils = require("./interlace"); +let paethPredictor = require("./paeth-predictor"); + +function getByteWidth(width, bpp, depth) { + let byteWidth = width * bpp; + if (depth !== 8) { + byteWidth = Math.ceil(byteWidth / (8 / depth)); + } + return byteWidth; +} + +let Filter = (module.exports = function (bitmapInfo, dependencies) { + let width = bitmapInfo.width; + let height = bitmapInfo.height; + let interlace = bitmapInfo.interlace; + let bpp = bitmapInfo.bpp; + let depth = bitmapInfo.depth; + + this.read = dependencies.read; + this.write = dependencies.write; + this.complete = dependencies.complete; + + this._imageIndex = 0; + this._images = []; + if (interlace) { + let passes = interlaceUtils.getImagePasses(width, height); + for (let i = 0; i < passes.length; i++) { + this._images.push({ + byteWidth: getByteWidth(passes[i].width, bpp, depth), + height: passes[i].height, + lineIndex: 0, + }); + } + } else { + this._images.push({ + byteWidth: getByteWidth(width, bpp, depth), + height: height, + lineIndex: 0, + }); + } + + // when filtering the line we look at the pixel to the left + // the spec also says it is done on a byte level regardless of the number of pixels + // so if the depth is byte compatible (8 or 16) we subtract the bpp in order to compare back + // a pixel rather than just a different byte part. However if we are sub byte, we ignore. + if (depth === 8) { + this._xComparison = bpp; + } else if (depth === 16) { + this._xComparison = bpp * 2; + } else { + this._xComparison = 1; + } +}); + +Filter.prototype.start = function () { + this.read( + this._images[this._imageIndex].byteWidth + 1, + this._reverseFilterLine.bind(this) + ); +}; + +Filter.prototype._unFilterType1 = function ( + rawData, + unfilteredLine, + byteWidth +) { + let xComparison = this._xComparison; + let xBiggerThan = xComparison - 1; + + for (let x = 0; x < byteWidth; x++) { + let rawByte = rawData[1 + x]; + let f1Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0; + unfilteredLine[x] = rawByte + f1Left; + } +}; + +Filter.prototype._unFilterType2 = function ( + rawData, + unfilteredLine, + byteWidth +) { + let lastLine = this._lastLine; + + for (let x = 0; x < byteWidth; x++) { + let rawByte = rawData[1 + x]; + let f2Up = lastLine ? lastLine[x] : 0; + unfilteredLine[x] = rawByte + f2Up; + } +}; + +Filter.prototype._unFilterType3 = function ( + rawData, + unfilteredLine, + byteWidth +) { + let xComparison = this._xComparison; + let xBiggerThan = xComparison - 1; + let lastLine = this._lastLine; + + for (let x = 0; x < byteWidth; x++) { + let rawByte = rawData[1 + x]; + let f3Up = lastLine ? lastLine[x] : 0; + let f3Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0; + let f3Add = Math.floor((f3Left + f3Up) / 2); + unfilteredLine[x] = rawByte + f3Add; + } +}; + +Filter.prototype._unFilterType4 = function ( + rawData, + unfilteredLine, + byteWidth +) { + let xComparison = this._xComparison; + let xBiggerThan = xComparison - 1; + let lastLine = this._lastLine; + + for (let x = 0; x < byteWidth; x++) { + let rawByte = rawData[1 + x]; + let f4Up = lastLine ? lastLine[x] : 0; + let f4Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0; + let f4UpLeft = x > xBiggerThan && lastLine ? lastLine[x - xComparison] : 0; + let f4Add = paethPredictor(f4Left, f4Up, f4UpLeft); + unfilteredLine[x] = rawByte + f4Add; + } +}; + +Filter.prototype._reverseFilterLine = function (rawData) { + let filter = rawData[0]; + let unfilteredLine; + let currentImage = this._images[this._imageIndex]; + let byteWidth = currentImage.byteWidth; + + if (filter === 0) { + unfilteredLine = rawData.slice(1, byteWidth + 1); + } else { + unfilteredLine = Buffer.alloc(byteWidth); + + switch (filter) { + case 1: + this._unFilterType1(rawData, unfilteredLine, byteWidth); + break; + case 2: + this._unFilterType2(rawData, unfilteredLine, byteWidth); + break; + case 3: + this._unFilterType3(rawData, unfilteredLine, byteWidth); + break; + case 4: + this._unFilterType4(rawData, unfilteredLine, byteWidth); + break; + default: + throw new Error("Unrecognised filter type - " + filter); + } + } + + this.write(unfilteredLine); + + currentImage.lineIndex++; + if (currentImage.lineIndex >= currentImage.height) { + this._lastLine = null; + this._imageIndex++; + currentImage = this._images[this._imageIndex]; + } else { + this._lastLine = unfilteredLine; + } + + if (currentImage) { + // read, using the byte width that may be from the new current image + this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this)); + } else { + this._lastLine = null; + this.complete(); + } +}; diff --git a/node_modules/pngjs/lib/format-normaliser.js b/node_modules/pngjs/lib/format-normaliser.js new file mode 100644 index 0000000..634d566 --- /dev/null +++ b/node_modules/pngjs/lib/format-normaliser.js @@ -0,0 +1,93 @@ +"use strict"; + +function dePalette(indata, outdata, width, height, palette) { + let pxPos = 0; + // use values from palette + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + let color = palette[indata[pxPos]]; + + if (!color) { + throw new Error("index " + indata[pxPos] + " not in palette"); + } + + for (let i = 0; i < 4; i++) { + outdata[pxPos + i] = color[i]; + } + pxPos += 4; + } + } +} + +function replaceTransparentColor(indata, outdata, width, height, transColor) { + let pxPos = 0; + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + let makeTrans = false; + + if (transColor.length === 1) { + if (transColor[0] === indata[pxPos]) { + makeTrans = true; + } + } else if ( + transColor[0] === indata[pxPos] && + transColor[1] === indata[pxPos + 1] && + transColor[2] === indata[pxPos + 2] + ) { + makeTrans = true; + } + if (makeTrans) { + for (let i = 0; i < 4; i++) { + outdata[pxPos + i] = 0; + } + } + pxPos += 4; + } + } +} + +function scaleDepth(indata, outdata, width, height, depth) { + let maxOutSample = 255; + let maxInSample = Math.pow(2, depth) - 1; + let pxPos = 0; + + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + for (let i = 0; i < 4; i++) { + outdata[pxPos + i] = Math.floor( + (indata[pxPos + i] * maxOutSample) / maxInSample + 0.5 + ); + } + pxPos += 4; + } + } +} + +module.exports = function (indata, imageData) { + let depth = imageData.depth; + let width = imageData.width; + let height = imageData.height; + let colorType = imageData.colorType; + let transColor = imageData.transColor; + let palette = imageData.palette; + + let outdata = indata; // only different for 16 bits + + if (colorType === 3) { + // paletted + dePalette(indata, outdata, width, height, palette); + } else { + if (transColor) { + replaceTransparentColor(indata, outdata, width, height, transColor); + } + // if it needs scaling + if (depth !== 8) { + // if we need to change the buffer size + if (depth === 16) { + outdata = Buffer.alloc(width * height * 4); + } + scaleDepth(indata, outdata, width, height, depth); + } + } + return outdata; +}; diff --git a/node_modules/pngjs/lib/interlace.js b/node_modules/pngjs/lib/interlace.js new file mode 100644 index 0000000..a035cb1 --- /dev/null +++ b/node_modules/pngjs/lib/interlace.js @@ -0,0 +1,95 @@ +"use strict"; + +// Adam 7 +// 0 1 2 3 4 5 6 7 +// 0 x 6 4 6 x 6 4 6 +// 1 7 7 7 7 7 7 7 7 +// 2 5 6 5 6 5 6 5 6 +// 3 7 7 7 7 7 7 7 7 +// 4 3 6 4 6 3 6 4 6 +// 5 7 7 7 7 7 7 7 7 +// 6 5 6 5 6 5 6 5 6 +// 7 7 7 7 7 7 7 7 7 + +let imagePasses = [ + { + // pass 1 - 1px + x: [0], + y: [0], + }, + { + // pass 2 - 1px + x: [4], + y: [0], + }, + { + // pass 3 - 2px + x: [0, 4], + y: [4], + }, + { + // pass 4 - 4px + x: [2, 6], + y: [0, 4], + }, + { + // pass 5 - 8px + x: [0, 2, 4, 6], + y: [2, 6], + }, + { + // pass 6 - 16px + x: [1, 3, 5, 7], + y: [0, 2, 4, 6], + }, + { + // pass 7 - 32px + x: [0, 1, 2, 3, 4, 5, 6, 7], + y: [1, 3, 5, 7], + }, +]; + +exports.getImagePasses = function (width, height) { + let images = []; + let xLeftOver = width % 8; + let yLeftOver = height % 8; + let xRepeats = (width - xLeftOver) / 8; + let yRepeats = (height - yLeftOver) / 8; + for (let i = 0; i < imagePasses.length; i++) { + let pass = imagePasses[i]; + let passWidth = xRepeats * pass.x.length; + let passHeight = yRepeats * pass.y.length; + for (let j = 0; j < pass.x.length; j++) { + if (pass.x[j] < xLeftOver) { + passWidth++; + } else { + break; + } + } + for (let j = 0; j < pass.y.length; j++) { + if (pass.y[j] < yLeftOver) { + passHeight++; + } else { + break; + } + } + if (passWidth > 0 && passHeight > 0) { + images.push({ width: passWidth, height: passHeight, index: i }); + } + } + return images; +}; + +exports.getInterlaceIterator = function (width) { + return function (x, y, pass) { + let outerXLeftOver = x % imagePasses[pass].x.length; + let outerX = + ((x - outerXLeftOver) / imagePasses[pass].x.length) * 8 + + imagePasses[pass].x[outerXLeftOver]; + let outerYLeftOver = y % imagePasses[pass].y.length; + let outerY = + ((y - outerYLeftOver) / imagePasses[pass].y.length) * 8 + + imagePasses[pass].y[outerYLeftOver]; + return outerX * 4 + outerY * width * 4; + }; +}; diff --git a/node_modules/pngjs/lib/packer-async.js b/node_modules/pngjs/lib/packer-async.js new file mode 100644 index 0000000..f3df73a --- /dev/null +++ b/node_modules/pngjs/lib/packer-async.js @@ -0,0 +1,50 @@ +"use strict"; + +let util = require("util"); +let Stream = require("stream"); +let constants = require("./constants"); +let Packer = require("./packer"); + +let PackerAsync = (module.exports = function (opt) { + Stream.call(this); + + let options = opt || {}; + + this._packer = new Packer(options); + this._deflate = this._packer.createDeflate(); + + this.readable = true; +}); +util.inherits(PackerAsync, Stream); + +PackerAsync.prototype.pack = function (data, width, height, gamma) { + // Signature + this.emit("data", Buffer.from(constants.PNG_SIGNATURE)); + this.emit("data", this._packer.packIHDR(width, height)); + + if (gamma) { + this.emit("data", this._packer.packGAMA(gamma)); + } + + let filteredData = this._packer.filterData(data, width, height); + + // compress it + this._deflate.on("error", this.emit.bind(this, "error")); + + this._deflate.on( + "data", + function (compressedData) { + this.emit("data", this._packer.packIDAT(compressedData)); + }.bind(this) + ); + + this._deflate.on( + "end", + function () { + this.emit("data", this._packer.packIEND()); + this.emit("end"); + }.bind(this) + ); + + this._deflate.end(filteredData); +}; diff --git a/node_modules/pngjs/lib/packer-sync.js b/node_modules/pngjs/lib/packer-sync.js new file mode 100644 index 0000000..f5ab0b3 --- /dev/null +++ b/node_modules/pngjs/lib/packer-sync.js @@ -0,0 +1,56 @@ +"use strict"; + +let hasSyncZlib = true; +let zlib = require("zlib"); +if (!zlib.deflateSync) { + hasSyncZlib = false; +} +let constants = require("./constants"); +let Packer = require("./packer"); + +module.exports = function (metaData, opt) { + if (!hasSyncZlib) { + throw new Error( + "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0" + ); + } + + let options = opt || {}; + + let packer = new Packer(options); + + let chunks = []; + + // Signature + chunks.push(Buffer.from(constants.PNG_SIGNATURE)); + + // Header + chunks.push(packer.packIHDR(metaData.width, metaData.height)); + + if (metaData.gamma) { + chunks.push(packer.packGAMA(metaData.gamma)); + } + + let filteredData = packer.filterData( + metaData.data, + metaData.width, + metaData.height + ); + + // compress it + let compressedData = zlib.deflateSync( + filteredData, + packer.getDeflateOptions() + ); + filteredData = null; + + if (!compressedData || !compressedData.length) { + throw new Error("bad png - invalid compressed data response"); + } + chunks.push(packer.packIDAT(compressedData)); + + // End + chunks.push(packer.packIEND()); + + return Buffer.concat(chunks); +}; diff --git a/node_modules/pngjs/lib/packer.js b/node_modules/pngjs/lib/packer.js new file mode 100644 index 0000000..4aba12c --- /dev/null +++ b/node_modules/pngjs/lib/packer.js @@ -0,0 +1,129 @@ +"use strict"; + +let constants = require("./constants"); +let CrcStream = require("./crc"); +let bitPacker = require("./bitpacker"); +let filter = require("./filter-pack"); +let zlib = require("zlib"); + +let Packer = (module.exports = function (options) { + this._options = options; + + options.deflateChunkSize = options.deflateChunkSize || 32 * 1024; + options.deflateLevel = + options.deflateLevel != null ? options.deflateLevel : 9; + options.deflateStrategy = + options.deflateStrategy != null ? options.deflateStrategy : 3; + options.inputHasAlpha = + options.inputHasAlpha != null ? options.inputHasAlpha : true; + options.deflateFactory = options.deflateFactory || zlib.createDeflate; + options.bitDepth = options.bitDepth || 8; + // This is outputColorType + options.colorType = + typeof options.colorType === "number" + ? options.colorType + : constants.COLORTYPE_COLOR_ALPHA; + options.inputColorType = + typeof options.inputColorType === "number" + ? options.inputColorType + : constants.COLORTYPE_COLOR_ALPHA; + + if ( + [ + constants.COLORTYPE_GRAYSCALE, + constants.COLORTYPE_COLOR, + constants.COLORTYPE_COLOR_ALPHA, + constants.COLORTYPE_ALPHA, + ].indexOf(options.colorType) === -1 + ) { + throw new Error( + "option color type:" + options.colorType + " is not supported at present" + ); + } + if ( + [ + constants.COLORTYPE_GRAYSCALE, + constants.COLORTYPE_COLOR, + constants.COLORTYPE_COLOR_ALPHA, + constants.COLORTYPE_ALPHA, + ].indexOf(options.inputColorType) === -1 + ) { + throw new Error( + "option input color type:" + + options.inputColorType + + " is not supported at present" + ); + } + if (options.bitDepth !== 8 && options.bitDepth !== 16) { + throw new Error( + "option bit depth:" + options.bitDepth + " is not supported at present" + ); + } +}); + +Packer.prototype.getDeflateOptions = function () { + return { + chunkSize: this._options.deflateChunkSize, + level: this._options.deflateLevel, + strategy: this._options.deflateStrategy, + }; +}; + +Packer.prototype.createDeflate = function () { + return this._options.deflateFactory(this.getDeflateOptions()); +}; + +Packer.prototype.filterData = function (data, width, height) { + // convert to correct format for filtering (e.g. right bpp and bit depth) + let packedData = bitPacker(data, width, height, this._options); + + // filter pixel data + let bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType]; + let filteredData = filter(packedData, width, height, this._options, bpp); + return filteredData; +}; + +Packer.prototype._packChunk = function (type, data) { + let len = data ? data.length : 0; + let buf = Buffer.alloc(len + 12); + + buf.writeUInt32BE(len, 0); + buf.writeUInt32BE(type, 4); + + if (data) { + data.copy(buf, 8); + } + + buf.writeInt32BE( + CrcStream.crc32(buf.slice(4, buf.length - 4)), + buf.length - 4 + ); + return buf; +}; + +Packer.prototype.packGAMA = function (gamma) { + let buf = Buffer.alloc(4); + buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0); + return this._packChunk(constants.TYPE_gAMA, buf); +}; + +Packer.prototype.packIHDR = function (width, height) { + let buf = Buffer.alloc(13); + buf.writeUInt32BE(width, 0); + buf.writeUInt32BE(height, 4); + buf[8] = this._options.bitDepth; // Bit depth + buf[9] = this._options.colorType; // colorType + buf[10] = 0; // compression + buf[11] = 0; // filter + buf[12] = 0; // interlace + + return this._packChunk(constants.TYPE_IHDR, buf); +}; + +Packer.prototype.packIDAT = function (data) { + return this._packChunk(constants.TYPE_IDAT, data); +}; + +Packer.prototype.packIEND = function () { + return this._packChunk(constants.TYPE_IEND, null); +}; diff --git a/node_modules/pngjs/lib/paeth-predictor.js b/node_modules/pngjs/lib/paeth-predictor.js new file mode 100644 index 0000000..9634497 --- /dev/null +++ b/node_modules/pngjs/lib/paeth-predictor.js @@ -0,0 +1,16 @@ +"use strict"; + +module.exports = function paethPredictor(left, above, upLeft) { + let paeth = left + above - upLeft; + let pLeft = Math.abs(paeth - left); + let pAbove = Math.abs(paeth - above); + let pUpLeft = Math.abs(paeth - upLeft); + + if (pLeft <= pAbove && pLeft <= pUpLeft) { + return left; + } + if (pAbove <= pUpLeft) { + return above; + } + return upLeft; +}; diff --git a/node_modules/pngjs/lib/parser-async.js b/node_modules/pngjs/lib/parser-async.js new file mode 100644 index 0000000..a69d153 --- /dev/null +++ b/node_modules/pngjs/lib/parser-async.js @@ -0,0 +1,165 @@ +"use strict"; + +let util = require("util"); +let zlib = require("zlib"); +let ChunkStream = require("./chunkstream"); +let FilterAsync = require("./filter-parse-async"); +let Parser = require("./parser"); +let bitmapper = require("./bitmapper"); +let formatNormaliser = require("./format-normaliser"); + +let ParserAsync = (module.exports = function (options) { + ChunkStream.call(this); + + this._parser = new Parser(options, { + read: this.read.bind(this), + error: this._handleError.bind(this), + metadata: this._handleMetaData.bind(this), + gamma: this.emit.bind(this, "gamma"), + palette: this._handlePalette.bind(this), + transColor: this._handleTransColor.bind(this), + finished: this._finished.bind(this), + inflateData: this._inflateData.bind(this), + simpleTransparency: this._simpleTransparency.bind(this), + headersFinished: this._headersFinished.bind(this), + }); + this._options = options; + this.writable = true; + + this._parser.start(); +}); +util.inherits(ParserAsync, ChunkStream); + +ParserAsync.prototype._handleError = function (err) { + this.emit("error", err); + + this.writable = false; + + this.destroy(); + + if (this._inflate && this._inflate.destroy) { + this._inflate.destroy(); + } + + if (this._filter) { + this._filter.destroy(); + // For backward compatibility with Node 7 and below. + // Suppress errors due to _inflate calling write() even after + // it's destroy()'ed. + this._filter.on("error", function () {}); + } + + this.errord = true; +}; + +ParserAsync.prototype._inflateData = function (data) { + if (!this._inflate) { + if (this._bitmapInfo.interlace) { + this._inflate = zlib.createInflate(); + + this._inflate.on("error", this.emit.bind(this, "error")); + this._filter.on("complete", this._complete.bind(this)); + + this._inflate.pipe(this._filter); + } else { + let rowSize = + ((this._bitmapInfo.width * + this._bitmapInfo.bpp * + this._bitmapInfo.depth + + 7) >> + 3) + + 1; + let imageSize = rowSize * this._bitmapInfo.height; + let chunkSize = Math.max(imageSize, zlib.Z_MIN_CHUNK); + + this._inflate = zlib.createInflate({ chunkSize: chunkSize }); + let leftToInflate = imageSize; + + let emitError = this.emit.bind(this, "error"); + this._inflate.on("error", function (err) { + if (!leftToInflate) { + return; + } + + emitError(err); + }); + this._filter.on("complete", this._complete.bind(this)); + + let filterWrite = this._filter.write.bind(this._filter); + this._inflate.on("data", function (chunk) { + if (!leftToInflate) { + return; + } + + if (chunk.length > leftToInflate) { + chunk = chunk.slice(0, leftToInflate); + } + + leftToInflate -= chunk.length; + + filterWrite(chunk); + }); + + this._inflate.on("end", this._filter.end.bind(this._filter)); + } + } + this._inflate.write(data); +}; + +ParserAsync.prototype._handleMetaData = function (metaData) { + this._metaData = metaData; + this._bitmapInfo = Object.create(metaData); + + this._filter = new FilterAsync(this._bitmapInfo); +}; + +ParserAsync.prototype._handleTransColor = function (transColor) { + this._bitmapInfo.transColor = transColor; +}; + +ParserAsync.prototype._handlePalette = function (palette) { + this._bitmapInfo.palette = palette; +}; + +ParserAsync.prototype._simpleTransparency = function () { + this._metaData.alpha = true; +}; + +ParserAsync.prototype._headersFinished = function () { + // Up until this point, we don't know if we have a tRNS chunk (alpha) + // so we can't emit metadata any earlier + this.emit("metadata", this._metaData); +}; + +ParserAsync.prototype._finished = function () { + if (this.errord) { + return; + } + + if (!this._inflate) { + this.emit("error", "No Inflate block"); + } else { + // no more data to inflate + this._inflate.end(); + } +}; + +ParserAsync.prototype._complete = function (filteredData) { + if (this.errord) { + return; + } + + let normalisedBitmapData; + + try { + let bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo); + + normalisedBitmapData = formatNormaliser(bitmapData, this._bitmapInfo); + bitmapData = null; + } catch (ex) { + this._handleError(ex); + return; + } + + this.emit("parsed", normalisedBitmapData); +}; diff --git a/node_modules/pngjs/lib/parser-sync.js b/node_modules/pngjs/lib/parser-sync.js new file mode 100644 index 0000000..e79796b --- /dev/null +++ b/node_modules/pngjs/lib/parser-sync.js @@ -0,0 +1,108 @@ +"use strict"; + +let hasSyncZlib = true; +let zlib = require("zlib"); +let inflateSync = require("./sync-inflate"); +if (!zlib.deflateSync) { + hasSyncZlib = false; +} +let SyncReader = require("./sync-reader"); +let FilterSync = require("./filter-parse-sync"); +let Parser = require("./parser"); +let bitmapper = require("./bitmapper"); +let formatNormaliser = require("./format-normaliser"); + +module.exports = function (buffer, options) { + if (!hasSyncZlib) { + throw new Error( + "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0" + ); + } + + let err; + function handleError(_err_) { + err = _err_; + } + + let metaData; + function handleMetaData(_metaData_) { + metaData = _metaData_; + } + + function handleTransColor(transColor) { + metaData.transColor = transColor; + } + + function handlePalette(palette) { + metaData.palette = palette; + } + + function handleSimpleTransparency() { + metaData.alpha = true; + } + + let gamma; + function handleGamma(_gamma_) { + gamma = _gamma_; + } + + let inflateDataList = []; + function handleInflateData(inflatedData) { + inflateDataList.push(inflatedData); + } + + let reader = new SyncReader(buffer); + + let parser = new Parser(options, { + read: reader.read.bind(reader), + error: handleError, + metadata: handleMetaData, + gamma: handleGamma, + palette: handlePalette, + transColor: handleTransColor, + inflateData: handleInflateData, + simpleTransparency: handleSimpleTransparency, + }); + + parser.start(); + reader.process(); + + if (err) { + throw err; + } + + //join together the inflate datas + let inflateData = Buffer.concat(inflateDataList); + inflateDataList.length = 0; + + let inflatedData; + if (metaData.interlace) { + inflatedData = zlib.inflateSync(inflateData); + } else { + let rowSize = + ((metaData.width * metaData.bpp * metaData.depth + 7) >> 3) + 1; + let imageSize = rowSize * metaData.height; + inflatedData = inflateSync(inflateData, { + chunkSize: imageSize, + maxLength: imageSize, + }); + } + inflateData = null; + + if (!inflatedData || !inflatedData.length) { + throw new Error("bad png - invalid inflate data response"); + } + + let unfilteredData = FilterSync.process(inflatedData, metaData); + inflateData = null; + + let bitmapData = bitmapper.dataToBitMap(unfilteredData, metaData); + unfilteredData = null; + + let normalisedBitmapData = formatNormaliser(bitmapData, metaData); + + metaData.data = normalisedBitmapData; + metaData.gamma = gamma || 0; + + return metaData; +}; diff --git a/node_modules/pngjs/lib/parser.js b/node_modules/pngjs/lib/parser.js new file mode 100644 index 0000000..51a8f2a --- /dev/null +++ b/node_modules/pngjs/lib/parser.js @@ -0,0 +1,290 @@ +"use strict"; + +let constants = require("./constants"); +let CrcCalculator = require("./crc"); + +let Parser = (module.exports = function (options, dependencies) { + this._options = options; + options.checkCRC = options.checkCRC !== false; + + this._hasIHDR = false; + this._hasIEND = false; + this._emittedHeadersFinished = false; + + // input flags/metadata + this._palette = []; + this._colorType = 0; + + this._chunks = {}; + this._chunks[constants.TYPE_IHDR] = this._handleIHDR.bind(this); + this._chunks[constants.TYPE_IEND] = this._handleIEND.bind(this); + this._chunks[constants.TYPE_IDAT] = this._handleIDAT.bind(this); + this._chunks[constants.TYPE_PLTE] = this._handlePLTE.bind(this); + this._chunks[constants.TYPE_tRNS] = this._handleTRNS.bind(this); + this._chunks[constants.TYPE_gAMA] = this._handleGAMA.bind(this); + + this.read = dependencies.read; + this.error = dependencies.error; + this.metadata = dependencies.metadata; + this.gamma = dependencies.gamma; + this.transColor = dependencies.transColor; + this.palette = dependencies.palette; + this.parsed = dependencies.parsed; + this.inflateData = dependencies.inflateData; + this.finished = dependencies.finished; + this.simpleTransparency = dependencies.simpleTransparency; + this.headersFinished = dependencies.headersFinished || function () {}; +}); + +Parser.prototype.start = function () { + this.read(constants.PNG_SIGNATURE.length, this._parseSignature.bind(this)); +}; + +Parser.prototype._parseSignature = function (data) { + let signature = constants.PNG_SIGNATURE; + + for (let i = 0; i < signature.length; i++) { + if (data[i] !== signature[i]) { + this.error(new Error("Invalid file signature")); + return; + } + } + this.read(8, this._parseChunkBegin.bind(this)); +}; + +Parser.prototype._parseChunkBegin = function (data) { + // chunk content length + let length = data.readUInt32BE(0); + + // chunk type + let type = data.readUInt32BE(4); + let name = ""; + for (let i = 4; i < 8; i++) { + name += String.fromCharCode(data[i]); + } + + //console.log('chunk ', name, length); + + // chunk flags + let ancillary = Boolean(data[4] & 0x20); // or critical + // priv = Boolean(data[5] & 0x20), // or public + // safeToCopy = Boolean(data[7] & 0x20); // or unsafe + + if (!this._hasIHDR && type !== constants.TYPE_IHDR) { + this.error(new Error("Expected IHDR on beggining")); + return; + } + + this._crc = new CrcCalculator(); + this._crc.write(Buffer.from(name)); + + if (this._chunks[type]) { + return this._chunks[type](length); + } + + if (!ancillary) { + this.error(new Error("Unsupported critical chunk type " + name)); + return; + } + + this.read(length + 4, this._skipChunk.bind(this)); +}; + +Parser.prototype._skipChunk = function (/*data*/) { + this.read(8, this._parseChunkBegin.bind(this)); +}; + +Parser.prototype._handleChunkEnd = function () { + this.read(4, this._parseChunkEnd.bind(this)); +}; + +Parser.prototype._parseChunkEnd = function (data) { + let fileCrc = data.readInt32BE(0); + let calcCrc = this._crc.crc32(); + + // check CRC + if (this._options.checkCRC && calcCrc !== fileCrc) { + this.error(new Error("Crc error - " + fileCrc + " - " + calcCrc)); + return; + } + + if (!this._hasIEND) { + this.read(8, this._parseChunkBegin.bind(this)); + } +}; + +Parser.prototype._handleIHDR = function (length) { + this.read(length, this._parseIHDR.bind(this)); +}; +Parser.prototype._parseIHDR = function (data) { + this._crc.write(data); + + let width = data.readUInt32BE(0); + let height = data.readUInt32BE(4); + let depth = data[8]; + let colorType = data[9]; // bits: 1 palette, 2 color, 4 alpha + let compr = data[10]; + let filter = data[11]; + let interlace = data[12]; + + // console.log(' width', width, 'height', height, + // 'depth', depth, 'colorType', colorType, + // 'compr', compr, 'filter', filter, 'interlace', interlace + // ); + + if ( + depth !== 8 && + depth !== 4 && + depth !== 2 && + depth !== 1 && + depth !== 16 + ) { + this.error(new Error("Unsupported bit depth " + depth)); + return; + } + if (!(colorType in constants.COLORTYPE_TO_BPP_MAP)) { + this.error(new Error("Unsupported color type")); + return; + } + if (compr !== 0) { + this.error(new Error("Unsupported compression method")); + return; + } + if (filter !== 0) { + this.error(new Error("Unsupported filter method")); + return; + } + if (interlace !== 0 && interlace !== 1) { + this.error(new Error("Unsupported interlace method")); + return; + } + + this._colorType = colorType; + + let bpp = constants.COLORTYPE_TO_BPP_MAP[this._colorType]; + + this._hasIHDR = true; + + this.metadata({ + width: width, + height: height, + depth: depth, + interlace: Boolean(interlace), + palette: Boolean(colorType & constants.COLORTYPE_PALETTE), + color: Boolean(colorType & constants.COLORTYPE_COLOR), + alpha: Boolean(colorType & constants.COLORTYPE_ALPHA), + bpp: bpp, + colorType: colorType, + }); + + this._handleChunkEnd(); +}; + +Parser.prototype._handlePLTE = function (length) { + this.read(length, this._parsePLTE.bind(this)); +}; +Parser.prototype._parsePLTE = function (data) { + this._crc.write(data); + + let entries = Math.floor(data.length / 3); + // console.log('Palette:', entries); + + for (let i = 0; i < entries; i++) { + this._palette.push([data[i * 3], data[i * 3 + 1], data[i * 3 + 2], 0xff]); + } + + this.palette(this._palette); + + this._handleChunkEnd(); +}; + +Parser.prototype._handleTRNS = function (length) { + this.simpleTransparency(); + this.read(length, this._parseTRNS.bind(this)); +}; +Parser.prototype._parseTRNS = function (data) { + this._crc.write(data); + + // palette + if (this._colorType === constants.COLORTYPE_PALETTE_COLOR) { + if (this._palette.length === 0) { + this.error(new Error("Transparency chunk must be after palette")); + return; + } + if (data.length > this._palette.length) { + this.error(new Error("More transparent colors than palette size")); + return; + } + for (let i = 0; i < data.length; i++) { + this._palette[i][3] = data[i]; + } + this.palette(this._palette); + } + + // for colorType 0 (grayscale) and 2 (rgb) + // there might be one gray/color defined as transparent + if (this._colorType === constants.COLORTYPE_GRAYSCALE) { + // grey, 2 bytes + this.transColor([data.readUInt16BE(0)]); + } + if (this._colorType === constants.COLORTYPE_COLOR) { + this.transColor([ + data.readUInt16BE(0), + data.readUInt16BE(2), + data.readUInt16BE(4), + ]); + } + + this._handleChunkEnd(); +}; + +Parser.prototype._handleGAMA = function (length) { + this.read(length, this._parseGAMA.bind(this)); +}; +Parser.prototype._parseGAMA = function (data) { + this._crc.write(data); + this.gamma(data.readUInt32BE(0) / constants.GAMMA_DIVISION); + + this._handleChunkEnd(); +}; + +Parser.prototype._handleIDAT = function (length) { + if (!this._emittedHeadersFinished) { + this._emittedHeadersFinished = true; + this.headersFinished(); + } + this.read(-length, this._parseIDAT.bind(this, length)); +}; +Parser.prototype._parseIDAT = function (length, data) { + this._crc.write(data); + + if ( + this._colorType === constants.COLORTYPE_PALETTE_COLOR && + this._palette.length === 0 + ) { + throw new Error("Expected palette not found"); + } + + this.inflateData(data); + let leftOverLength = length - data.length; + + if (leftOverLength > 0) { + this._handleIDAT(leftOverLength); + } else { + this._handleChunkEnd(); + } +}; + +Parser.prototype._handleIEND = function (length) { + this.read(length, this._parseIEND.bind(this)); +}; +Parser.prototype._parseIEND = function (data) { + this._crc.write(data); + + this._hasIEND = true; + this._handleChunkEnd(); + + if (this.finished) { + this.finished(); + } +}; diff --git a/node_modules/pngjs/lib/png-sync.js b/node_modules/pngjs/lib/png-sync.js new file mode 100644 index 0000000..68cac9b --- /dev/null +++ b/node_modules/pngjs/lib/png-sync.js @@ -0,0 +1,12 @@ +"use strict"; + +let parse = require("./parser-sync"); +let pack = require("./packer-sync"); + +exports.read = function (buffer, options) { + return parse(buffer, options || {}); +}; + +exports.write = function (png, options) { + return pack(png, options); +}; diff --git a/node_modules/pngjs/lib/png.js b/node_modules/pngjs/lib/png.js new file mode 100644 index 0000000..0b8af3f --- /dev/null +++ b/node_modules/pngjs/lib/png.js @@ -0,0 +1,194 @@ +"use strict"; + +let util = require("util"); +let Stream = require("stream"); +let Parser = require("./parser-async"); +let Packer = require("./packer-async"); +let PNGSync = require("./png-sync"); + +let PNG = (exports.PNG = function (options) { + Stream.call(this); + + options = options || {}; // eslint-disable-line no-param-reassign + + // coerce pixel dimensions to integers (also coerces undefined -> 0): + this.width = options.width | 0; + this.height = options.height | 0; + + this.data = + this.width > 0 && this.height > 0 + ? Buffer.alloc(4 * this.width * this.height) + : null; + + if (options.fill && this.data) { + this.data.fill(0); + } + + this.gamma = 0; + this.readable = this.writable = true; + + this._parser = new Parser(options); + + this._parser.on("error", this.emit.bind(this, "error")); + this._parser.on("close", this._handleClose.bind(this)); + this._parser.on("metadata", this._metadata.bind(this)); + this._parser.on("gamma", this._gamma.bind(this)); + this._parser.on( + "parsed", + function (data) { + this.data = data; + this.emit("parsed", data); + }.bind(this) + ); + + this._packer = new Packer(options); + this._packer.on("data", this.emit.bind(this, "data")); + this._packer.on("end", this.emit.bind(this, "end")); + this._parser.on("close", this._handleClose.bind(this)); + this._packer.on("error", this.emit.bind(this, "error")); +}); +util.inherits(PNG, Stream); + +PNG.sync = PNGSync; + +PNG.prototype.pack = function () { + if (!this.data || !this.data.length) { + this.emit("error", "No data provided"); + return this; + } + + process.nextTick( + function () { + this._packer.pack(this.data, this.width, this.height, this.gamma); + }.bind(this) + ); + + return this; +}; + +PNG.prototype.parse = function (data, callback) { + if (callback) { + let onParsed, onError; + + onParsed = function (parsedData) { + this.removeListener("error", onError); + + this.data = parsedData; + callback(null, this); + }.bind(this); + + onError = function (err) { + this.removeListener("parsed", onParsed); + + callback(err, null); + }.bind(this); + + this.once("parsed", onParsed); + this.once("error", onError); + } + + this.end(data); + return this; +}; + +PNG.prototype.write = function (data) { + this._parser.write(data); + return true; +}; + +PNG.prototype.end = function (data) { + this._parser.end(data); +}; + +PNG.prototype._metadata = function (metadata) { + this.width = metadata.width; + this.height = metadata.height; + + this.emit("metadata", metadata); +}; + +PNG.prototype._gamma = function (gamma) { + this.gamma = gamma; +}; + +PNG.prototype._handleClose = function () { + if (!this._parser.writable && !this._packer.readable) { + this.emit("close"); + } +}; + +PNG.bitblt = function (src, dst, srcX, srcY, width, height, deltaX, deltaY) { + // eslint-disable-line max-params + // coerce pixel dimensions to integers (also coerces undefined -> 0): + /* eslint-disable no-param-reassign */ + srcX |= 0; + srcY |= 0; + width |= 0; + height |= 0; + deltaX |= 0; + deltaY |= 0; + /* eslint-enable no-param-reassign */ + + if ( + srcX > src.width || + srcY > src.height || + srcX + width > src.width || + srcY + height > src.height + ) { + throw new Error("bitblt reading outside image"); + } + + if ( + deltaX > dst.width || + deltaY > dst.height || + deltaX + width > dst.width || + deltaY + height > dst.height + ) { + throw new Error("bitblt writing outside image"); + } + + for (let y = 0; y < height; y++) { + src.data.copy( + dst.data, + ((deltaY + y) * dst.width + deltaX) << 2, + ((srcY + y) * src.width + srcX) << 2, + ((srcY + y) * src.width + srcX + width) << 2 + ); + } +}; + +PNG.prototype.bitblt = function ( + dst, + srcX, + srcY, + width, + height, + deltaX, + deltaY +) { + // eslint-disable-line max-params + + PNG.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY); + return this; +}; + +PNG.adjustGamma = function (src) { + if (src.gamma) { + for (let y = 0; y < src.height; y++) { + for (let x = 0; x < src.width; x++) { + let idx = (src.width * y + x) << 2; + + for (let i = 0; i < 3; i++) { + let sample = src.data[idx + i] / 255; + sample = Math.pow(sample, 1 / 2.2 / src.gamma); + src.data[idx + i] = Math.round(sample * 255); + } + } + } + src.gamma = 0; + } +}; + +PNG.prototype.adjustGamma = function () { + PNG.adjustGamma(this); +}; diff --git a/node_modules/pngjs/lib/sync-inflate.js b/node_modules/pngjs/lib/sync-inflate.js new file mode 100644 index 0000000..4da0d5f --- /dev/null +++ b/node_modules/pngjs/lib/sync-inflate.js @@ -0,0 +1,168 @@ +"use strict"; + +let assert = require("assert").ok; +let zlib = require("zlib"); +let util = require("util"); + +let kMaxLength = require("buffer").kMaxLength; + +function Inflate(opts) { + if (!(this instanceof Inflate)) { + return new Inflate(opts); + } + + if (opts && opts.chunkSize < zlib.Z_MIN_CHUNK) { + opts.chunkSize = zlib.Z_MIN_CHUNK; + } + + zlib.Inflate.call(this, opts); + + // Node 8 --> 9 compatibility check + this._offset = this._offset === undefined ? this._outOffset : this._offset; + this._buffer = this._buffer || this._outBuffer; + + if (opts && opts.maxLength != null) { + this._maxLength = opts.maxLength; + } +} + +function createInflate(opts) { + return new Inflate(opts); +} + +function _close(engine, callback) { + if (callback) { + process.nextTick(callback); + } + + // Caller may invoke .close after a zlib error (which will null _handle). + if (!engine._handle) { + return; + } + + engine._handle.close(); + engine._handle = null; +} + +Inflate.prototype._processChunk = function (chunk, flushFlag, asyncCb) { + if (typeof asyncCb === "function") { + return zlib.Inflate._processChunk.call(this, chunk, flushFlag, asyncCb); + } + + let self = this; + + let availInBefore = chunk && chunk.length; + let availOutBefore = this._chunkSize - this._offset; + let leftToInflate = this._maxLength; + let inOff = 0; + + let buffers = []; + let nread = 0; + + let error; + this.on("error", function (err) { + error = err; + }); + + function handleChunk(availInAfter, availOutAfter) { + if (self._hadError) { + return; + } + + let have = availOutBefore - availOutAfter; + assert(have >= 0, "have should not go down"); + + if (have > 0) { + let out = self._buffer.slice(self._offset, self._offset + have); + self._offset += have; + + if (out.length > leftToInflate) { + out = out.slice(0, leftToInflate); + } + + buffers.push(out); + nread += out.length; + leftToInflate -= out.length; + + if (leftToInflate === 0) { + return false; + } + } + + if (availOutAfter === 0 || self._offset >= self._chunkSize) { + availOutBefore = self._chunkSize; + self._offset = 0; + self._buffer = Buffer.allocUnsafe(self._chunkSize); + } + + if (availOutAfter === 0) { + inOff += availInBefore - availInAfter; + availInBefore = availInAfter; + + return true; + } + + return false; + } + + assert(this._handle, "zlib binding closed"); + let res; + do { + res = this._handle.writeSync( + flushFlag, + chunk, // in + inOff, // in_off + availInBefore, // in_len + this._buffer, // out + this._offset, //out_off + availOutBefore + ); // out_len + // Node 8 --> 9 compatibility check + res = res || this._writeState; + } while (!this._hadError && handleChunk(res[0], res[1])); + + if (this._hadError) { + throw error; + } + + if (nread >= kMaxLength) { + _close(this); + throw new RangeError( + "Cannot create final Buffer. It would be larger than 0x" + + kMaxLength.toString(16) + + " bytes" + ); + } + + let buf = Buffer.concat(buffers, nread); + _close(this); + + return buf; +}; + +util.inherits(Inflate, zlib.Inflate); + +function zlibBufferSync(engine, buffer) { + if (typeof buffer === "string") { + buffer = Buffer.from(buffer); + } + if (!(buffer instanceof Buffer)) { + throw new TypeError("Not a string or buffer"); + } + + let flushFlag = engine._finishFlushFlag; + if (flushFlag == null) { + flushFlag = zlib.Z_FINISH; + } + + return engine._processChunk(buffer, flushFlag); +} + +function inflateSync(buffer, opts) { + return zlibBufferSync(new Inflate(opts), buffer); +} + +module.exports = exports = inflateSync; +exports.Inflate = Inflate; +exports.createInflate = createInflate; +exports.inflateSync = inflateSync; diff --git a/node_modules/pngjs/lib/sync-reader.js b/node_modules/pngjs/lib/sync-reader.js new file mode 100644 index 0000000..15cbd4c --- /dev/null +++ b/node_modules/pngjs/lib/sync-reader.js @@ -0,0 +1,45 @@ +"use strict"; + +let SyncReader = (module.exports = function (buffer) { + this._buffer = buffer; + this._reads = []; +}); + +SyncReader.prototype.read = function (length, callback) { + this._reads.push({ + length: Math.abs(length), // if length < 0 then at most this length + allowLess: length < 0, + func: callback, + }); +}; + +SyncReader.prototype.process = function () { + // as long as there is any data and read requests + while (this._reads.length > 0 && this._buffer.length) { + let read = this._reads[0]; + + if ( + this._buffer.length && + (this._buffer.length >= read.length || read.allowLess) + ) { + // ok there is any data so that we can satisfy this request + this._reads.shift(); // == read + + let buf = this._buffer; + + this._buffer = buf.slice(read.length); + + read.func.call(this, buf.slice(0, read.length)); + } else { + break; + } + } + + if (this._reads.length > 0) { + return new Error("There are some read requests waitng on finished stream"); + } + + if (this._buffer.length > 0) { + return new Error("unrecognised content at end of stream"); + } +}; diff --git a/node_modules/pngjs/package.json b/node_modules/pngjs/package.json new file mode 100644 index 0000000..12a9871 --- /dev/null +++ b/node_modules/pngjs/package.json @@ -0,0 +1,73 @@ +{ + "name": "pngjs", + "version": "5.0.0", + "description": "PNG encoder/decoder in pure JS, supporting any bit size & interlace, async & sync with full test suite.", + "contributors": [ + "Alexandre Paré", + "Gaurav Mali", + "Gusts Kaksis", + "Kuba Niegowski", + "Luke Page", + "Pietajan De Potter", + "Steven Sojka", + "liangzeng", + "Michael Vogt", + "Xin-Xin Wang", + "toriningen", + "Eugene Kulabuhov" + ], + "homepage": "https://github.com/lukeapage/pngjs", + "keywords": [ + "PNG", + "decoder", + "encoder", + "js-png", + "node-png", + "parser", + "png", + "png-js", + "png-parse", + "pngjs" + ], + "engines": { + "node": ">=10.13.0" + }, + "main": "./lib/png.js", + "directories": { + "lib": "lib", + "example": "examples", + "test": "test" + }, + "scripts": { + "build": "yarn prepublish", + "prepublish": "yarn browserify", + "browserify": "browserify lib/png.js --standalone png > browser.js", + "coverage": "nyc --reporter=lcov --reporter=text-summary tape test/*-spec.js nolarge", + "test": "yarn lint && yarn prettier:check && tape test/*-spec.js | tap-dot && node test/run-compare", + "lint": "eslint .", + "prettier:write": "prettier --write .", + "prettier:check": "prettier --check ." + }, + "repository": { + "type": "git", + "url": "git://github.com/lukeapage/pngjs.git" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/lukeapage/pngjs/issues" + }, + "devDependencies": { + "browserify": "16.5.1", + "buffer-equal": "1.0.0", + "codecov": "3.6.5", + "connect": "3.7.0", + "eslint": "6.8.0", + "eslint-config-prettier": "6.10.1", + "nyc": "15.0.1", + "prettier": "2.0.4", + "puppeteer": "2.1.1", + "serve-static": "1.14.1", + "tap-dot": "2.0.0", + "tape": "4.13.2" + } +} diff --git a/node_modules/qrcode/README.md b/node_modules/qrcode/README.md new file mode 100644 index 0000000..510e6b9 --- /dev/null +++ b/node_modules/qrcode/README.md @@ -0,0 +1,770 @@ +# node-qrcode +> QR code/2d barcode generator. + +[![Travis](https://img.shields.io/travis/soldair/node-qrcode.svg?style=flat-square)](http://travis-ci.org/soldair/node-qrcode) +[![npm](https://img.shields.io/npm/v/qrcode.svg?style=flat-square)](https://www.npmjs.com/package/qrcode) +[![npm](https://img.shields.io/npm/dt/qrcode.svg?style=flat-square)](https://www.npmjs.com/package/qrcode) +[![npm](https://img.shields.io/npm/l/qrcode.svg?style=flat-square)](https://github.com/soldair/node-qrcode/blob/master/license) + +- [Highlights](#highlights) +- [Installation](#installation) +- [Usage](#usage) +- [Error correction level](#error-correction-level) +- [QR Code capacity](#qr-code-capacity) +- [Encoding Modes](#encoding-modes) +- [Binary data](#binary-data) +- [Multibyte characters](#multibyte-characters) +- [API](#api) +- [GS1 QR Codes](#gs1-qr-codes) +- [Credits](#credits) +- [License](#license) + +## Highlights +- Works on server and client (and react native with svg) +- CLI utility +- Save QR code as image +- Support for Numeric, Alphanumeric, Kanji and Byte mode +- Support for mixed modes +- Support for chinese, cyrillic, greek and japanese characters +- Support for multibyte characters (like emojis :smile:) +- Auto generates optimized segments for best data compression and smallest QR Code size +- App agnostic readability, QR Codes by definition are app agnostic + +## Installation +Inside your project folder do: + +```shell +npm install --save qrcode +``` + +or, install it globally to use `qrcode` from the command line to save qrcode images or generate ones you can view in your terminal. + +```shell +npm install -g qrcode +``` + +## Usage +### CLI + +``` +Usage: qrcode [options] + +QR Code options: + -v, --qversion QR Code symbol version (1 - 40) [number] + -e, --error Error correction level [choices: "L", "M", "Q", "H"] + -m, --mask Mask pattern (0 - 7) [number] + +Renderer options: + -t, --type Output type [choices: "png", "svg", "utf8"] + -w, --width Image width (px) [number] + -s, --scale Scale factor [number] + -q, --qzone Quiet zone size [number] + -l, --lightcolor Light RGBA hex color + -d, --darkcolor Dark RGBA hex color + --small Output smaller QR code to terminal [boolean] + +Options: + -o, --output Output file + -h, --help Show help [boolean] + --version Show version number [boolean] + +Examples: + qrcode "some text" Draw in terminal window + qrcode -o out.png "some text" Save as png image + qrcode -d F00 -o out.png "some text" Use red as foreground color +``` +If not specified, output type is guessed from file extension.
+Recognized extensions are `png`, `svg` and `txt`. + +### Browser +`node-qrcode` can be used in browser through module bundlers like [Browserify](https://github.com/substack/node-browserify) and [Webpack](https://github.com/webpack/webpack) or by including the precompiled bundle present in `build/` folder. + +#### Module bundlers +```html + + + + + + + +``` + +```javascript +// index.js -> bundle.js +var QRCode = require('qrcode') +var canvas = document.getElementById('canvas') + +QRCode.toCanvas(canvas, 'sample text', function (error) { + if (error) console.error(error) + console.log('success!'); +}) +``` + +#### Precompiled bundle +```html + + + + +``` + +If you install through `npm`, precompiled files will be available in `node_modules/qrcode/build/` folder. + +The precompiled bundle have support for [Internet Explorer 10+, Safari 5.1+, and all evergreen browsers](https://browserl.ist/?q=defaults%2C+IE+%3E%3D+10%2C+Safari+%3E%3D+5.1). + +### NodeJS +Require the module `qrcode` + +```javascript +var QRCode = require('qrcode') + +QRCode.toDataURL('I am a pony!', function (err, url) { + console.log(url) +}) +``` + +render a qrcode for the terminal +```js +var QRCode = require('qrcode') + +QRCode.toString('I am a pony!',{type:'terminal'}, function (err, url) { + console.log(url) +}) +``` + +### ES6/ES7 +Promises and Async/Await can be used in place of callback function. + +```javascript +import QRCode from 'qrcode' + +// With promises +QRCode.toDataURL('I am a pony!') + .then(url => { + console.log(url) + }) + .catch(err => { + console.error(err) + }) + +// With async/await +const generateQR = async text => { + try { + console.log(await QRCode.toDataURL(text)) + } catch (err) { + console.error(err) + } +} +``` + +## Error correction level +Error correction capability allows to successfully scan a QR Code even if the symbol is dirty or damaged. +Four levels are available to choose according to the operating environment. + +Higher levels offer a better error resistance but reduce the symbol's capacity.
+If the chances that the QR Code symbol may be corrupted are low (for example if it is showed through a monitor) +is possible to safely use a low error level such as `Low` or `Medium`. + +Possible levels are shown below: + +| Level | Error resistance | +|------------------|:----------------:| +| **L** (Low) | **~7%** | +| **M** (Medium) | **~15%** | +| **Q** (Quartile) | **~25%** | +| **H** (High) | **~30%** | + +The percentage indicates the maximum amount of damaged surface after which the symbol becomes unreadable. + +Error level can be set through `options.errorCorrectionLevel` property.
+If not specified, the default value is `M`. + +```javascript +QRCode.toDataURL('some text', { errorCorrectionLevel: 'H' }, function (err, url) { + console.log(url) +}) +``` + +## QR Code capacity +Capacity depends on symbol version and error correction level. Also encoding modes may influence the amount of storable data. + +The QR Code versions range from version **1** to version **40**.
+Each version has a different number of modules (black and white dots), which define the symbol's size. +For version 1 they are `21x21`, for version 2 `25x25` e so on. +Higher is the version, more are the storable data, and of course bigger will be the QR Code symbol. + +The table below shows the maximum number of storable characters in each encoding mode and for each error correction level. + +| Mode | L | M | Q | H | +|--------------|------|------|------|------| +| Numeric | 7089 | 5596 | 3993 | 3057 | +| Alphanumeric | 4296 | 3391 | 2420 | 1852 | +| Byte | 2953 | 2331 | 1663 | 1273 | +| Kanji | 1817 | 1435 | 1024 | 784 | + +**Note:** Maximum characters number can be different when using [Mixed modes](#mixed-modes). + +QR Code version can be set through `options.version` property.
+If no version is specified, the more suitable value will be used. Unless a specific version is required, this option is not needed. + +```javascript +QRCode.toDataURL('some text', { version: 2 }, function (err, url) { + console.log(url) +}) +``` + +## Encoding modes +Modes can be used to encode a string in a more efficient way.
+A mode may be more suitable than others depending on the string content. +A list of supported modes are shown in the table below: + +| Mode | Characters | Compression | +|--------------|-----------------------------------------------------------|-------------------------------------------| +| Numeric | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 | 3 characters are represented by 10 bits | +| Alphanumeric | 0–9, A–Z (upper-case only), space, $, %, *, +, -, ., /, : | 2 characters are represented by 11 bits | +| Kanji | Characters from the Shift JIS system based on JIS X 0208 | 2 kanji are represented by 13 bits | +| Byte | Characters from the ISO/IEC 8859-1 character set | Each characters are represented by 8 bits | + +Choose the right mode may be tricky if the input text is unknown.
+In these cases **Byte** mode is the best choice since all characters can be encoded with it. (See [Multibyte characters](#multibyte-characters))
+However, if the QR Code reader supports mixed modes, using [Auto mode](#auto-mode) may produce better results. + +### Mixed modes +Mixed modes are also possible. A QR code can be generated from a series of segments having different encoding modes to optimize the data compression.
+However, switching from a mode to another has a cost which may lead to a worst result if it's not taken into account. +See [Manual mode](#manual-mode) for an example of how to specify segments with different encoding modes. + +### Auto mode +By **default**, automatic mode selection is used.
+The input string is automatically splitted in various segments optimized to produce the shortest possible bitstream using mixed modes.
+This is the preferred way to generate the QR Code. + +For example, the string **ABCDE12345678?A1A** will be splitted in 3 segments with the following modes: + +| Segment | Mode | +|----------|--------------| +| ABCDE | Alphanumeric | +| 12345678 | Numeric | +| ?A1A | Byte | + +Any other combinations of segments and modes will result in a longer bitstream.
+If you need to keep the QR Code size small, this mode will produce the best results. + +### Manual mode +If auto mode doesn't work for you or you have specific needs, is also possible to manually specify each segment with the relative mode. +In this way no segment optimizations will be applied under the hood.
+Segments list can be passed as an array of object: + +```javascript + var QRCode = require('qrcode') + + var segs = [ + { data: 'ABCDEFG', mode: 'alphanumeric' }, + { data: '0123456', mode: 'numeric' } + ] + + QRCode.toDataURL(segs, function (err, url) { + console.log(url) + }) +``` + +### Kanji mode +With kanji mode is possible to encode characters from the Shift JIS system in an optimized way.
+Unfortunately, there isn't a way to calculate a Shifted JIS values from, for example, a character encoded in UTF-8, for this reason a conversion table from the input characters to the SJIS values is needed.
+This table is not included by default in the bundle to keep the size as small as possible. + +If your application requires kanji support, you will need to pass a function that will take care of converting the input characters to appropriate values. + +An helper method is provided by the lib through an optional file that you can include as shown in the example below. + +**Note:** Support for Kanji mode is only needed if you want to benefit of the data compression, otherwise is still possible to encode kanji using Byte mode (See [Multibyte characters](#multibyte-characters)). + +```javascript + var QRCode = require('qrcode') + var toSJIS = require('qrcode/helper/to-sjis') + + QRCode.toDataURL(kanjiString, { toSJISFunc: toSJIS }, function (err, url) { + console.log(url) + }) +``` + +With precompiled bundle: + +```html + + + + + +``` + +## Binary data +QR Codes can hold arbitrary byte-based binary data. If you attempt to create a binary QR Code by first converting the data to a JavaScript string, it will fail to encode propery because string encoding adds additional bytes. Instead, you must pass a [`Uint8ClampedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray) or compatible array, or a Node [Buffer](https://nodejs.org/api/buffer.html), as follows: + +```javascript +// Regular array example +// WARNING: Element values will be clamped to 0-255 even if your data contains higher values. +const QRCode = require('qrcode') +QRCode.toFile( + 'foo.png', + [{ data: [253,254,255], mode: 'byte' }], + ...options..., + ...callback... +) +``` + +```javascript +// Uint8ClampedArray example +const QRCode = require('qrcode') + +QRCode.toFile( + 'foo.png', + [{ data: new Uint8ClampedArray([253,254,255]), mode: 'byte' }], + ...options..., + ...callback... +) +``` + +```javascript +// Node Buffer example +// WARNING: Element values will be clamped to 0-255 even if your data contains higher values. +const QRCode = require('qrcode') + +QRCode.toFile( + 'foo.png', + [{ data: Buffer.from([253,254,255]), mode: 'byte' }], + ...options..., + ...callback... +) +``` + +TypeScript users: if you are using [@types/qrcode](https://www.npmjs.com/package/@types/qrcode), you will need to add a `// @ts-ignore` above the data segment because it expects `data: string`. + +## Multibyte characters +Support for multibyte characters isn't present in the initial QR Code standard, but is possible to encode UTF-8 characters in Byte mode. + +QR Codes provide a way to specify a different type of character set through ECI (Extended Channel Interpretation), but it's not fully implemented in this lib yet. + +Most QR Code readers, however, are able to recognize multibyte characters even without ECI. + +Note that a single Kanji/Kana or Emoji can take up to 4 bytes. + +## API +Browser: +- [create()](#createtext-options) +- [toCanvas()](#tocanvascanvaselement-text-options-cberror) +- [toDataURL()](#todataurltext-options-cberror-url) +- [toString()](#tostringtext-options-cberror-string) + +Server: +- [create()](#createtext-options) +- [toCanvas()](#tocanvascanvas-text-options-cberror) +- [toDataURL()](#todataurltext-options-cberror-url-1) +- [toString()](#tostringtext-options-cberror-string-1) +- [toFile()](#tofilepath-text-options-cberror) +- [toFileStream()](#tofilestreamstream-text-options) + +### Browser API +#### `create(text, [options])` +Creates QR Code symbol and returns a qrcode object. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +See [QR Code options](#qr-code-options). + +##### `returns` +Type: `Object` + +```javascript +// QRCode object +{ + modules, // Bitmatrix class with modules data + version, // Calculated QR Code version + errorCorrectionLevel, // Error Correction Level + maskPattern, // Calculated Mask pattern + segments // Generated segments +} +``` + +
+ +#### `toCanvas(canvasElement, text, [options], [cb(error)])` +#### `toCanvas(text, [options], [cb(error, canvas)])` +Draws qr code symbol to canvas.
+If `canvasElement` is omitted a new canvas is returned. + +##### `canvasElement` +Type: `DOMElement` + +Canvas where to draw QR Code. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +See [Options](#options). + +##### `cb` +Type: `Function` + +Callback function called on finish. + +##### Example +```javascript +QRCode.toCanvas('text', { errorCorrectionLevel: 'H' }, function (err, canvas) { + if (err) throw err + + var container = document.getElementById('container') + container.appendChild(canvas) +}) +``` + +
+ +#### `toDataURL(text, [options], [cb(error, url)])` +#### `toDataURL(canvasElement, text, [options], [cb(error, url)])` +Returns a Data URI containing a representation of the QR Code image.
+If provided, `canvasElement` will be used as canvas to generate the data URI. + +##### `canvasElement` +Type: `DOMElement` + +Canvas where to draw QR Code. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +- ###### `type` + Type: `String`
+ Default: `image/png` + + Data URI format.
+ Possible values are: `image/png`, `image/jpeg`, `image/webp`.
+ +- ###### `rendererOpts.quality` + Type: `Number`
+ Default: `0.92` + + A Number between `0` and `1` indicating image quality if the requested type is `image/jpeg` or `image/webp`. + +See [Options](#options) for other settings. + +##### `cb` +Type: `Function` + +Callback function called on finish. + +##### Example +```javascript +var opts = { + errorCorrectionLevel: 'H', + type: 'image/jpeg', + quality: 0.3, + margin: 1, + color: { + dark:"#010599FF", + light:"#FFBF60FF" + } +} + +QRCode.toDataURL('text', opts, function (err, url) { + if (err) throw err + + var img = document.getElementById('image') + img.src = url +}) +``` +
+ +#### `toString(text, [options], [cb(error, string)])` + +Returns a string representation of the QR Code.
+ + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +- ###### `type` + Type: `String`
+ Default: `utf8` + + Output format.
+ Possible values are: `terminal`,`utf8`, and `svg`. + +See [Options](#options) for other settings. + +##### `cb` +Type: `Function` + +Callback function called on finish. + +##### Example +```javascript +QRCode.toString('http://www.google.com', function (err, string) { + if (err) throw err + console.log(string) +}) +``` + +
+ + +### Server API +#### `create(text, [options])` +See [create](#createtext-options). + +
+ +#### `toCanvas(canvas, text, [options], [cb(error)])` +Draws qr code symbol to [node canvas](https://github.com/Automattic/node-canvas). + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +See [Options](#options). + +##### `cb` +Type: `Function` + +Callback function called on finish. + +
+ +#### `toDataURL(text, [options], [cb(error, url)])` +Returns a Data URI containing a representation of the QR Code image.
+Only works with `image/png` type for now. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +See [Options](#options) for other settings. + +##### `cb` +Type: `Function` + +Callback function called on finish. + +
+ +#### `toString(text, [options], [cb(error, string)])` +Returns a string representation of the QR Code.
+If choosen output format is `svg` it will returns a string containing xml code. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +- ###### `type` + Type: `String`
+ Default: `utf8` + + Output format.
+ Possible values are: `utf8`, `svg`, `terminal`. + +See [Options](#options) for other settings. + +##### `cb` +Type: `Function` + +Callback function called on finish. + +##### Example +```javascript +QRCode.toString('http://www.google.com', function (err, string) { + if (err) throw err + console.log(string) +}) +``` + +
+ +#### `toFile(path, text, [options], [cb(error)])` +Saves QR Code to image file.
+If `options.type` is not specified, the format will be guessed from file extension.
+Recognized extensions are `png`, `svg`, `txt`. + +##### `path` +Type: `String` + +Path where to save the file. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +- ###### `type` + Type: `String`
+ Default: `png` + + Output format.
+ Possible values are: `png`, `svg`, `utf8`. + +- ###### `rendererOpts.deflateLevel` **(png only)** + Type: `Number`
+ Default: `9` + + Compression level for deflate. + +- ###### `rendererOpts.deflateStrategy` **(png only)** + Type: `Number`
+ Default: `3` + + Compression strategy for deflate. + +See [Options](#options) for other settings. + +##### `cb` +Type: `Function` + +Callback function called on finish. + +##### Example +```javascript +QRCode.toFile('path/to/filename.png', 'Some text', { + color: { + dark: '#00F', // Blue dots + light: '#0000' // Transparent background + } +}, function (err) { + if (err) throw err + console.log('done') +}) +``` + +
+ +#### `toFileStream(stream, text, [options])` +Writes QR Code image to stream. Only works with `png` format for now. + +##### `stream` +Type: `stream.Writable` + +Node stream. + +##### `text` +Type: `String|Array` + +Text to encode or a list of objects describing segments. + +##### `options` +See [Options](#options). + +
+ +### Options + +#### QR Code options +##### `version` + Type: `Number`
+ + QR Code version. If not specified the more suitable value will be calculated. + +##### `errorCorrectionLevel` + Type: `String`
+ Default: `M` + + Error correction level.
+ Possible values are `low, medium, quartile, high` or `L, M, Q, H`. + +##### `maskPattern` + Type: `Number`
+ + Mask pattern used to mask the symbol.
+ Possible values are `0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`.
+ If not specified the more suitable value will be calculated. + +##### `toSJISFunc` + Type: `Function`
+ + Helper function used internally to convert a kanji to its Shift JIS value.
+ Provide this function if you need support for Kanji mode. + +#### Renderers options +##### `margin` + Type: `Number`
+ Default: `4` + + Define how much wide the quiet zone should be. + +##### `scale` + Type: `Number`
+ Default: `4` + + Scale factor. A value of `1` means 1px per modules (black dots). + +##### `small` + Type: `Boolean`
+ Default: `false` + + Relevant only for terminal renderer. Outputs smaller QR code. + +##### `width` + Type: `Number`
+ + Forces a specific width for the output image.
+ If width is too small to contain the qr symbol, this option will be ignored.
+ Takes precedence over `scale`. + +##### `color.dark` +Type: `String`
+Default: `#000000ff` + +Color of dark module. Value must be in hex format (RGBA).
+Note: dark color should always be darker than `color.light`. + +##### `color.light` +Type: `String`
+Default: `#ffffffff` + +Color of light module. Value must be in hex format (RGBA).
+ +
+ +## GS1 QR Codes +There was a real good discussion here about them. but in short any qrcode generator will make gs1 compatible qrcodes, but what defines a gs1 qrcode is a header with metadata that describes your gs1 information. + +https://github.com/soldair/node-qrcode/issues/45 + + +## Credits +This lib is based on "QRCode for JavaScript" which Kazuhiko Arase thankfully MIT licensed. + +## License +[MIT](https://github.com/soldair/node-qrcode/blob/master/license) + +The word "QR Code" is registered trademark of:
+DENSO WAVE INCORPORATED diff --git a/node_modules/qrcode/bin/qrcode b/node_modules/qrcode/bin/qrcode new file mode 100644 index 0000000..dd990b6 --- /dev/null +++ b/node_modules/qrcode/bin/qrcode @@ -0,0 +1,159 @@ +#!/usr/bin/env node +var yargs = require('yargs') +var qr = require('../lib') + +function save (file, text, options) { + qr.toFile(file, text, options, function (err, data) { + if (err) { + console.error('Error:', err.message) + process.exit(1) + } + + console.log('saved qrcode to: ' + file + '\n') + }) +} + +function print (text, options) { + options.type = 'terminal' + qr.toString(text, options, function (err, text) { + if (err) { + console.error('Error:', err.message) + process.exit(1) + } + + console.log(text) + }) +} + +function parseOptions (args) { + return { + version: args.qversion, + errorCorrectionLevel: args.error, + type: args.type, + small: !!args.small, + inverse: !!args.inverse, + maskPattern: args.mask, + margin: args.qzone, + width: args.width, + scale: args.scale, + color: { + light: args.lightcolor, + dark: args.darkcolor + } + } +} + +function processInputs (text, opts) { + if (!text.length) { + yargs.showHelp() + process.exit(1) + } + + if (opts.output) { + save(opts.output, text, parseOptions(opts)) + } else { + print(text, parseOptions(opts)) + } +} + +var argv = yargs + .detectLocale(false) + .usage('Usage: $0 [options] ') + .option('v', { + alias: 'qversion', + description: 'QR Code symbol version (1 - 40)', + group: 'QR Code options:', + type: 'number' + }) + .option('e', { + alias: 'error', + description: 'Error correction level', + choices: ['L', 'M', 'Q', 'H'], + group: 'QR Code options:' + }) + .option('m', { + alias: 'mask', + description: 'Mask pattern (0 - 7)', + group: 'QR Code options:', + type: 'number' + }) + .option('t', { + alias: 'type', + description: 'Output type', + choices: ['png', 'svg', 'utf8'], + implies: 'output', + group: 'Renderer options:' + }) + .option('i', { + alias: 'inverse', + type: 'boolean', + description: 'Invert colors', + group: 'Renderer options:' + }) + .option('w', { + alias: 'width', + description: 'Image width (px)', + conflicts: 'scale', + group: 'Renderer options:', + type: 'number' + }) + .option('s', { + alias: 'scale', + description: 'Scale factor', + conflicts: 'width', + group: 'Renderer options:', + type: 'number' + }) + .option('q', { + alias: 'qzone', + description: 'Quiet zone size', + group: 'Renderer options:', + type: 'number' + }) + .option('l', { + alias: 'lightcolor', + description: 'Light RGBA hex color', + group: 'Renderer options:' + }) + .option('d', { + alias: 'darkcolor', + description: 'Dark RGBA hex color', + group: 'Renderer options:' + }) + .option('small', { + type: 'boolean', + description: 'Output smaller QR code to terminal', + conflicts: 'type', + group: 'Renderer options:' + }) + .option('o', { + alias: 'output', + description: 'Output file' + }) + .help('h') + .alias('h', 'help') + .version() + .example('$0 "some text"', 'Draw in terminal window') + .example('$0 -o out.png "some text"', 'Save as png image') + .example('$0 -d F00 -o out.png "some text"', 'Use red as foreground color') + .parserConfiguration({'parse-numbers': false}) + .argv + +if (process.stdin.isTTY) { + processInputs(argv._.join(' '), argv) +} else { + var text = '' + process.stdin.setEncoding('utf8') + process.stdin.on('readable', function () { + var chunk = process.stdin.read() + if (chunk !== null) { + text += chunk + } + }) + + process.stdin.on('end', function () { + // this process can be run as a command outside of a tty so if there was no + // data on stdin read from argv + processInputs(text.length?text:argv._.join(' '), argv) + }) +} diff --git a/node_modules/qrcode/helper/to-sjis-browser.js b/node_modules/qrcode/helper/to-sjis-browser.js new file mode 100644 index 0000000..1c9b3aa --- /dev/null +++ b/node_modules/qrcode/helper/to-sjis-browser.js @@ -0,0 +1,2 @@ +/* global QRCode */ +QRCode.toSJIS = require('./to-sjis') diff --git a/node_modules/qrcode/helper/to-sjis.js b/node_modules/qrcode/helper/to-sjis.js new file mode 100644 index 0000000..594c6f7 --- /dev/null +++ b/node_modules/qrcode/helper/to-sjis.js @@ -0,0 +1,105 @@ +const SJIS_UTF8 = [ + [0x8140, ' 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈〉《》「」『』【】+-±×'], + [0x8180, '÷=≠<>≦≧∞∴♂♀°′″℃'], + [0x818f, '¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼'], + [0x81a6, '※〒→←↑↓〓'], + [0x81b8, '∈∋⊆⊇⊂⊃∪∩'], + [0x81c8, '∧∨¬⇒⇔∀∃'], + [0x81da, '∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬'], + [0x81f0, 'ʼn♯♭♪†‡¶'], + [0x824f, '0123456789'], + [0x8260, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'], + [0x8281, 'abcdefghijklmnopqrstuvwxyz'], + [0x829f, 'ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん'], + [0x8340, 'ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミ'], + [0x8380, 'ムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ'], + [0x839f, 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ'], + [0x83bf, 'αβγδεζηθικλμνξοπρστυφχψω'], + [0x8440, 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'], + [0x8470, 'абвгдеёжзийклмн'], + [0x8480, 'опрстуфхцчшщъыьэюя'], + [0x8780, '〝〟'], + [0x889f, '亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣'], + [0x88e0, '謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭'], + [0x8940, '院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円'], + [0x8980, '園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改'], + [0x8a40, '魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫'], + [0x8a80, '橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄'], + [0x8b40, '機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救'], + [0x8b80, '朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈'], + [0x8c40, '掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨'], + [0x8c80, '劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向'], + [0x8d40, '后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降'], + [0x8d80, '項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷'], + [0x8e40, '察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止'], + [0x8e80, '死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周'], + [0x8f40, '宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳'], + [0x8f80, '準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾'], + [0x9040, '拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨'], + [0x9080, '逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線'], + [0x9140, '繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻'], + [0x9180, '操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只'], + [0x9240, '叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄'], + [0x9280, '逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓'], + [0x9340, '邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬'], + [0x9380, '凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入'], + [0x9440, '如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅'], + [0x9480, '楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美'], + [0x9540, '鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷'], + [0x9580, '斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋'], + [0x9640, '法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆'], + [0x9680, '摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒'], + [0x9740, '諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲'], + [0x9780, '沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯'], + [0x9840, '蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕'], + [0x989f, '弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲'], + [0x9940, '僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭'], + [0x9980, '凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨'], + [0x9a40, '咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸'], + [0x9a80, '噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩'], + [0x9b40, '奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀'], + [0x9b80, '它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏'], + [0x9c40, '廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠'], + [0x9c80, '怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛'], + [0x9d40, '戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫'], + [0x9d80, '捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼'], + [0x9e40, '曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎'], + [0x9e80, '梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣'], + [0x9f40, '檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯'], + [0x9f80, '麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌'], + [0xe040, '漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝'], + [0xe080, '烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱'], + [0xe140, '瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿'], + [0xe180, '痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬'], + [0xe240, '磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰'], + [0xe280, '窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆'], + [0xe340, '紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷'], + [0xe380, '縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋'], + [0xe440, '隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤'], + [0xe480, '艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈'], + [0xe540, '蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬'], + [0xe580, '蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞'], + [0xe640, '襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧'], + [0xe680, '諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊'], + [0xe740, '蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜'], + [0xe780, '轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮'], + [0xe840, '錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙'], + [0xe880, '閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰'], + [0xe940, '顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃'], + [0xe980, '騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈'], + [0xea40, '鵝鵞鵤鵑鵐鵙鵲鶉鶇鶫鵯鵺鶚鶤鶩鶲鷄鷁鶻鶸鶺鷆鷏鷂鷙鷓鷸鷦鷭鷯鷽鸚鸛鸞鹵鹹鹽麁麈麋麌麒麕麑麝麥麩麸麪麭靡黌黎黏黐黔黜點黝黠黥黨黯'], + [0xea80, '黴黶黷黹黻黼黽鼇鼈皷鼕鼡鼬鼾齊齒齔齣齟齠齡齦齧齬齪齷齲齶龕龜龠堯槇遙瑤凜熙'] +] + +module.exports = function toSJIS (utf8Char) { + if (!utf8Char || utf8Char === '') return + + for (let i = 0; i < SJIS_UTF8.length; i++) { + const kanji = SJIS_UTF8[i][1] + + const posIndex = kanji.indexOf(utf8Char) + if (posIndex >= 0) { + return SJIS_UTF8[i][0] + posIndex + } + } +} diff --git a/node_modules/qrcode/lib/browser.js b/node_modules/qrcode/lib/browser.js new file mode 100644 index 0000000..dc8a999 --- /dev/null +++ b/node_modules/qrcode/lib/browser.js @@ -0,0 +1,76 @@ + +const canPromise = require('./can-promise') + +const QRCode = require('./core/qrcode') +const CanvasRenderer = require('./renderer/canvas') +const SvgRenderer = require('./renderer/svg-tag.js') + +function renderCanvas (renderFunc, canvas, text, opts, cb) { + const args = [].slice.call(arguments, 1) + const argsNum = args.length + const isLastArgCb = typeof args[argsNum - 1] === 'function' + + if (!isLastArgCb && !canPromise()) { + throw new Error('Callback required as last argument') + } + + if (isLastArgCb) { + if (argsNum < 2) { + throw new Error('Too few arguments provided') + } + + if (argsNum === 2) { + cb = text + text = canvas + canvas = opts = undefined + } else if (argsNum === 3) { + if (canvas.getContext && typeof cb === 'undefined') { + cb = opts + opts = undefined + } else { + cb = opts + opts = text + text = canvas + canvas = undefined + } + } + } else { + if (argsNum < 1) { + throw new Error('Too few arguments provided') + } + + if (argsNum === 1) { + text = canvas + canvas = opts = undefined + } else if (argsNum === 2 && !canvas.getContext) { + opts = text + text = canvas + canvas = undefined + } + + return new Promise(function (resolve, reject) { + try { + const data = QRCode.create(text, opts) + resolve(renderFunc(data, canvas, opts)) + } catch (e) { + reject(e) + } + }) + } + + try { + const data = QRCode.create(text, opts) + cb(null, renderFunc(data, canvas, opts)) + } catch (e) { + cb(e) + } +} + +exports.create = QRCode.create +exports.toCanvas = renderCanvas.bind(null, CanvasRenderer.render) +exports.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL) + +// only svg for now. +exports.toString = renderCanvas.bind(null, function (data, _, opts) { + return SvgRenderer.render(data, opts) +}) diff --git a/node_modules/qrcode/lib/can-promise.js b/node_modules/qrcode/lib/can-promise.js new file mode 100644 index 0000000..77267f1 --- /dev/null +++ b/node_modules/qrcode/lib/can-promise.js @@ -0,0 +1,7 @@ +// can-promise has a crash in some versions of react native that dont have +// standard global objects +// https://github.com/soldair/node-qrcode/issues/157 + +module.exports = function () { + return typeof Promise === 'function' && Promise.prototype && Promise.prototype.then +} diff --git a/node_modules/qrcode/lib/core/alignment-pattern.js b/node_modules/qrcode/lib/core/alignment-pattern.js new file mode 100644 index 0000000..63c3154 --- /dev/null +++ b/node_modules/qrcode/lib/core/alignment-pattern.js @@ -0,0 +1,83 @@ +/** + * Alignment pattern are fixed reference pattern in defined positions + * in a matrix symbology, which enables the decode software to re-synchronise + * the coordinate mapping of the image modules in the event of moderate amounts + * of distortion of the image. + * + * Alignment patterns are present only in QR Code symbols of version 2 or larger + * and their number depends on the symbol version. + */ + +const getSymbolSize = require('./utils').getSymbolSize + +/** + * Calculate the row/column coordinates of the center module of each alignment pattern + * for the specified QR Code version. + * + * The alignment patterns are positioned symmetrically on either side of the diagonal + * running from the top left corner of the symbol to the bottom right corner. + * + * Since positions are simmetrical only half of the coordinates are returned. + * Each item of the array will represent in turn the x and y coordinate. + * @see {@link getPositions} + * + * @param {Number} version QR Code version + * @return {Array} Array of coordinate + */ +exports.getRowColCoords = function getRowColCoords (version) { + if (version === 1) return [] + + const posCount = Math.floor(version / 7) + 2 + const size = getSymbolSize(version) + const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2 + const positions = [size - 7] // Last coord is always (size - 7) + + for (let i = 1; i < posCount - 1; i++) { + positions[i] = positions[i - 1] - intervals + } + + positions.push(6) // First coord is always 6 + + return positions.reverse() +} + +/** + * Returns an array containing the positions of each alignment pattern. + * Each array's element represent the center point of the pattern as (x, y) coordinates + * + * Coordinates are calculated expanding the row/column coordinates returned by {@link getRowColCoords} + * and filtering out the items that overlaps with finder pattern + * + * @example + * For a Version 7 symbol {@link getRowColCoords} returns values 6, 22 and 38. + * The alignment patterns, therefore, are to be centered on (row, column) + * positions (6,22), (22,6), (22,22), (22,38), (38,22), (38,38). + * Note that the coordinates (6,6), (6,38), (38,6) are occupied by finder patterns + * and are not therefore used for alignment patterns. + * + * let pos = getPositions(7) + * // [[6,22], [22,6], [22,22], [22,38], [38,22], [38,38]] + * + * @param {Number} version QR Code version + * @return {Array} Array of coordinates + */ +exports.getPositions = function getPositions (version) { + const coords = [] + const pos = exports.getRowColCoords(version) + const posLength = pos.length + + for (let i = 0; i < posLength; i++) { + for (let j = 0; j < posLength; j++) { + // Skip if position is occupied by finder patterns + if ((i === 0 && j === 0) || // top-left + (i === 0 && j === posLength - 1) || // bottom-left + (i === posLength - 1 && j === 0)) { // top-right + continue + } + + coords.push([pos[i], pos[j]]) + } + } + + return coords +} diff --git a/node_modules/qrcode/lib/core/alphanumeric-data.js b/node_modules/qrcode/lib/core/alphanumeric-data.js new file mode 100644 index 0000000..29ddf50 --- /dev/null +++ b/node_modules/qrcode/lib/core/alphanumeric-data.js @@ -0,0 +1,59 @@ +const Mode = require('./mode') + +/** + * Array of characters available in alphanumeric mode + * + * As per QR Code specification, to each character + * is assigned a value from 0 to 44 which in this case coincides + * with the array index + * + * @type {Array} + */ +const ALPHA_NUM_CHARS = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + ' ', '$', '%', '*', '+', '-', '.', '/', ':' +] + +function AlphanumericData (data) { + this.mode = Mode.ALPHANUMERIC + this.data = data +} + +AlphanumericData.getBitsLength = function getBitsLength (length) { + return 11 * Math.floor(length / 2) + 6 * (length % 2) +} + +AlphanumericData.prototype.getLength = function getLength () { + return this.data.length +} + +AlphanumericData.prototype.getBitsLength = function getBitsLength () { + return AlphanumericData.getBitsLength(this.data.length) +} + +AlphanumericData.prototype.write = function write (bitBuffer) { + let i + + // Input data characters are divided into groups of two characters + // and encoded as 11-bit binary codes. + for (i = 0; i + 2 <= this.data.length; i += 2) { + // The character value of the first character is multiplied by 45 + let value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45 + + // The character value of the second digit is added to the product + value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1]) + + // The sum is then stored as 11-bit binary number + bitBuffer.put(value, 11) + } + + // If the number of input data characters is not a multiple of two, + // the character value of the final character is encoded as a 6-bit binary number. + if (this.data.length % 2) { + bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6) + } +} + +module.exports = AlphanumericData diff --git a/node_modules/qrcode/lib/core/bit-buffer.js b/node_modules/qrcode/lib/core/bit-buffer.js new file mode 100644 index 0000000..5b41d3d --- /dev/null +++ b/node_modules/qrcode/lib/core/bit-buffer.js @@ -0,0 +1,37 @@ +function BitBuffer () { + this.buffer = [] + this.length = 0 +} + +BitBuffer.prototype = { + + get: function (index) { + const bufIndex = Math.floor(index / 8) + return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) === 1 + }, + + put: function (num, length) { + for (let i = 0; i < length; i++) { + this.putBit(((num >>> (length - i - 1)) & 1) === 1) + } + }, + + getLengthInBits: function () { + return this.length + }, + + putBit: function (bit) { + const bufIndex = Math.floor(this.length / 8) + if (this.buffer.length <= bufIndex) { + this.buffer.push(0) + } + + if (bit) { + this.buffer[bufIndex] |= (0x80 >>> (this.length % 8)) + } + + this.length++ + } +} + +module.exports = BitBuffer diff --git a/node_modules/qrcode/lib/core/bit-matrix.js b/node_modules/qrcode/lib/core/bit-matrix.js new file mode 100644 index 0000000..439138b --- /dev/null +++ b/node_modules/qrcode/lib/core/bit-matrix.js @@ -0,0 +1,65 @@ +/** + * Helper class to handle QR Code symbol modules + * + * @param {Number} size Symbol size + */ +function BitMatrix (size) { + if (!size || size < 1) { + throw new Error('BitMatrix size must be defined and greater than 0') + } + + this.size = size + this.data = new Uint8Array(size * size) + this.reservedBit = new Uint8Array(size * size) +} + +/** + * Set bit value at specified location + * If reserved flag is set, this bit will be ignored during masking process + * + * @param {Number} row + * @param {Number} col + * @param {Boolean} value + * @param {Boolean} reserved + */ +BitMatrix.prototype.set = function (row, col, value, reserved) { + const index = row * this.size + col + this.data[index] = value + if (reserved) this.reservedBit[index] = true +} + +/** + * Returns bit value at specified location + * + * @param {Number} row + * @param {Number} col + * @return {Boolean} + */ +BitMatrix.prototype.get = function (row, col) { + return this.data[row * this.size + col] +} + +/** + * Applies xor operator at specified location + * (used during masking process) + * + * @param {Number} row + * @param {Number} col + * @param {Boolean} value + */ +BitMatrix.prototype.xor = function (row, col, value) { + this.data[row * this.size + col] ^= value +} + +/** + * Check if bit at specified location is reserved + * + * @param {Number} row + * @param {Number} col + * @return {Boolean} + */ +BitMatrix.prototype.isReserved = function (row, col) { + return this.reservedBit[row * this.size + col] +} + +module.exports = BitMatrix diff --git a/node_modules/qrcode/lib/core/byte-data.js b/node_modules/qrcode/lib/core/byte-data.js new file mode 100644 index 0000000..d562fcc --- /dev/null +++ b/node_modules/qrcode/lib/core/byte-data.js @@ -0,0 +1,30 @@ +const Mode = require('./mode') + +function ByteData (data) { + this.mode = Mode.BYTE + if (typeof (data) === 'string') { + this.data = new TextEncoder().encode(data) + } else { + this.data = new Uint8Array(data) + } +} + +ByteData.getBitsLength = function getBitsLength (length) { + return length * 8 +} + +ByteData.prototype.getLength = function getLength () { + return this.data.length +} + +ByteData.prototype.getBitsLength = function getBitsLength () { + return ByteData.getBitsLength(this.data.length) +} + +ByteData.prototype.write = function (bitBuffer) { + for (let i = 0, l = this.data.length; i < l; i++) { + bitBuffer.put(this.data[i], 8) + } +} + +module.exports = ByteData diff --git a/node_modules/qrcode/lib/core/error-correction-code.js b/node_modules/qrcode/lib/core/error-correction-code.js new file mode 100644 index 0000000..5f2fceb --- /dev/null +++ b/node_modules/qrcode/lib/core/error-correction-code.js @@ -0,0 +1,135 @@ +const ECLevel = require('./error-correction-level') + +const EC_BLOCKS_TABLE = [ +// L M Q H + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 2, 2, + 1, 2, 2, 4, + 1, 2, 4, 4, + 2, 4, 4, 4, + 2, 4, 6, 5, + 2, 4, 6, 6, + 2, 5, 8, 8, + 4, 5, 8, 8, + 4, 5, 8, 11, + 4, 8, 10, 11, + 4, 9, 12, 16, + 4, 9, 16, 16, + 6, 10, 12, 18, + 6, 10, 17, 16, + 6, 11, 16, 19, + 6, 13, 18, 21, + 7, 14, 21, 25, + 8, 16, 20, 25, + 8, 17, 23, 25, + 9, 17, 23, 34, + 9, 18, 25, 30, + 10, 20, 27, 32, + 12, 21, 29, 35, + 12, 23, 34, 37, + 12, 25, 34, 40, + 13, 26, 35, 42, + 14, 28, 38, 45, + 15, 29, 40, 48, + 16, 31, 43, 51, + 17, 33, 45, 54, + 18, 35, 48, 57, + 19, 37, 51, 60, + 19, 38, 53, 63, + 20, 40, 56, 66, + 21, 43, 59, 70, + 22, 45, 62, 74, + 24, 47, 65, 77, + 25, 49, 68, 81 +] + +const EC_CODEWORDS_TABLE = [ +// L M Q H + 7, 10, 13, 17, + 10, 16, 22, 28, + 15, 26, 36, 44, + 20, 36, 52, 64, + 26, 48, 72, 88, + 36, 64, 96, 112, + 40, 72, 108, 130, + 48, 88, 132, 156, + 60, 110, 160, 192, + 72, 130, 192, 224, + 80, 150, 224, 264, + 96, 176, 260, 308, + 104, 198, 288, 352, + 120, 216, 320, 384, + 132, 240, 360, 432, + 144, 280, 408, 480, + 168, 308, 448, 532, + 180, 338, 504, 588, + 196, 364, 546, 650, + 224, 416, 600, 700, + 224, 442, 644, 750, + 252, 476, 690, 816, + 270, 504, 750, 900, + 300, 560, 810, 960, + 312, 588, 870, 1050, + 336, 644, 952, 1110, + 360, 700, 1020, 1200, + 390, 728, 1050, 1260, + 420, 784, 1140, 1350, + 450, 812, 1200, 1440, + 480, 868, 1290, 1530, + 510, 924, 1350, 1620, + 540, 980, 1440, 1710, + 570, 1036, 1530, 1800, + 570, 1064, 1590, 1890, + 600, 1120, 1680, 1980, + 630, 1204, 1770, 2100, + 660, 1260, 1860, 2220, + 720, 1316, 1950, 2310, + 750, 1372, 2040, 2430 +] + +/** + * Returns the number of error correction block that the QR Code should contain + * for the specified version and error correction level. + * + * @param {Number} version QR Code version + * @param {Number} errorCorrectionLevel Error correction level + * @return {Number} Number of error correction blocks + */ +exports.getBlocksCount = function getBlocksCount (version, errorCorrectionLevel) { + switch (errorCorrectionLevel) { + case ECLevel.L: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 0] + case ECLevel.M: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 1] + case ECLevel.Q: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 2] + case ECLevel.H: + return EC_BLOCKS_TABLE[(version - 1) * 4 + 3] + default: + return undefined + } +} + +/** + * Returns the number of error correction codewords to use for the specified + * version and error correction level. + * + * @param {Number} version QR Code version + * @param {Number} errorCorrectionLevel Error correction level + * @return {Number} Number of error correction codewords + */ +exports.getTotalCodewordsCount = function getTotalCodewordsCount (version, errorCorrectionLevel) { + switch (errorCorrectionLevel) { + case ECLevel.L: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0] + case ECLevel.M: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1] + case ECLevel.Q: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2] + case ECLevel.H: + return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3] + default: + return undefined + } +} diff --git a/node_modules/qrcode/lib/core/error-correction-level.js b/node_modules/qrcode/lib/core/error-correction-level.js new file mode 100644 index 0000000..07433d6 --- /dev/null +++ b/node_modules/qrcode/lib/core/error-correction-level.js @@ -0,0 +1,50 @@ +exports.L = { bit: 1 } +exports.M = { bit: 0 } +exports.Q = { bit: 3 } +exports.H = { bit: 2 } + +function fromString (string) { + if (typeof string !== 'string') { + throw new Error('Param is not a string') + } + + const lcStr = string.toLowerCase() + + switch (lcStr) { + case 'l': + case 'low': + return exports.L + + case 'm': + case 'medium': + return exports.M + + case 'q': + case 'quartile': + return exports.Q + + case 'h': + case 'high': + return exports.H + + default: + throw new Error('Unknown EC Level: ' + string) + } +} + +exports.isValid = function isValid (level) { + return level && typeof level.bit !== 'undefined' && + level.bit >= 0 && level.bit < 4 +} + +exports.from = function from (value, defaultValue) { + if (exports.isValid(value)) { + return value + } + + try { + return fromString(value) + } catch (e) { + return defaultValue + } +} diff --git a/node_modules/qrcode/lib/core/finder-pattern.js b/node_modules/qrcode/lib/core/finder-pattern.js new file mode 100644 index 0000000..4613c04 --- /dev/null +++ b/node_modules/qrcode/lib/core/finder-pattern.js @@ -0,0 +1,22 @@ +const getSymbolSize = require('./utils').getSymbolSize +const FINDER_PATTERN_SIZE = 7 + +/** + * Returns an array containing the positions of each finder pattern. + * Each array's element represent the top-left point of the pattern as (x, y) coordinates + * + * @param {Number} version QR Code version + * @return {Array} Array of coordinates + */ +exports.getPositions = function getPositions (version) { + const size = getSymbolSize(version) + + return [ + // top-left + [0, 0], + // top-right + [size - FINDER_PATTERN_SIZE, 0], + // bottom-left + [0, size - FINDER_PATTERN_SIZE] + ] +} diff --git a/node_modules/qrcode/lib/core/format-info.js b/node_modules/qrcode/lib/core/format-info.js new file mode 100644 index 0000000..11fe9ef --- /dev/null +++ b/node_modules/qrcode/lib/core/format-info.js @@ -0,0 +1,29 @@ +const Utils = require('./utils') + +const G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0) +const G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1) +const G15_BCH = Utils.getBCHDigit(G15) + +/** + * Returns format information with relative error correction bits + * + * The format information is a 15-bit sequence containing 5 data bits, + * with 10 error correction bits calculated using the (15, 5) BCH code. + * + * @param {Number} errorCorrectionLevel Error correction level + * @param {Number} mask Mask pattern + * @return {Number} Encoded format information bits + */ +exports.getEncodedBits = function getEncodedBits (errorCorrectionLevel, mask) { + const data = ((errorCorrectionLevel.bit << 3) | mask) + let d = data << 10 + + while (Utils.getBCHDigit(d) - G15_BCH >= 0) { + d ^= (G15 << (Utils.getBCHDigit(d) - G15_BCH)) + } + + // xor final data with mask pattern in order to ensure that + // no combination of Error Correction Level and data mask pattern + // will result in an all-zero data string + return ((data << 10) | d) ^ G15_MASK +} diff --git a/node_modules/qrcode/lib/core/galois-field.js b/node_modules/qrcode/lib/core/galois-field.js new file mode 100644 index 0000000..8125179 --- /dev/null +++ b/node_modules/qrcode/lib/core/galois-field.js @@ -0,0 +1,69 @@ +const EXP_TABLE = new Uint8Array(512) +const LOG_TABLE = new Uint8Array(256) +/** + * Precompute the log and anti-log tables for faster computation later + * + * For each possible value in the galois field 2^8, we will pre-compute + * the logarithm and anti-logarithm (exponential) of this value + * + * ref {@link https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Introduction_to_mathematical_fields} + */ +;(function initTables () { + let x = 1 + for (let i = 0; i < 255; i++) { + EXP_TABLE[i] = x + LOG_TABLE[x] = i + + x <<= 1 // multiply by 2 + + // The QR code specification says to use byte-wise modulo 100011101 arithmetic. + // This means that when a number is 256 or larger, it should be XORed with 0x11D. + if (x & 0x100) { // similar to x >= 256, but a lot faster (because 0x100 == 256) + x ^= 0x11D + } + } + + // Optimization: double the size of the anti-log table so that we don't need to mod 255 to + // stay inside the bounds (because we will mainly use this table for the multiplication of + // two GF numbers, no more). + // @see {@link mul} + for (let i = 255; i < 512; i++) { + EXP_TABLE[i] = EXP_TABLE[i - 255] + } +}()) + +/** + * Returns log value of n inside Galois Field + * + * @param {Number} n + * @return {Number} + */ +exports.log = function log (n) { + if (n < 1) throw new Error('log(' + n + ')') + return LOG_TABLE[n] +} + +/** + * Returns anti-log value of n inside Galois Field + * + * @param {Number} n + * @return {Number} + */ +exports.exp = function exp (n) { + return EXP_TABLE[n] +} + +/** + * Multiplies two number inside Galois Field + * + * @param {Number} x + * @param {Number} y + * @return {Number} + */ +exports.mul = function mul (x, y) { + if (x === 0 || y === 0) return 0 + + // should be EXP_TABLE[(LOG_TABLE[x] + LOG_TABLE[y]) % 255] if EXP_TABLE wasn't oversized + // @see {@link initTables} + return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]] +} diff --git a/node_modules/qrcode/lib/core/kanji-data.js b/node_modules/qrcode/lib/core/kanji-data.js new file mode 100644 index 0000000..a1d9a69 --- /dev/null +++ b/node_modules/qrcode/lib/core/kanji-data.js @@ -0,0 +1,54 @@ +const Mode = require('./mode') +const Utils = require('./utils') + +function KanjiData (data) { + this.mode = Mode.KANJI + this.data = data +} + +KanjiData.getBitsLength = function getBitsLength (length) { + return length * 13 +} + +KanjiData.prototype.getLength = function getLength () { + return this.data.length +} + +KanjiData.prototype.getBitsLength = function getBitsLength () { + return KanjiData.getBitsLength(this.data.length) +} + +KanjiData.prototype.write = function (bitBuffer) { + let i + + // In the Shift JIS system, Kanji characters are represented by a two byte combination. + // These byte values are shifted from the JIS X 0208 values. + // JIS X 0208 gives details of the shift coded representation. + for (i = 0; i < this.data.length; i++) { + let value = Utils.toSJIS(this.data[i]) + + // For characters with Shift JIS values from 0x8140 to 0x9FFC: + if (value >= 0x8140 && value <= 0x9FFC) { + // Subtract 0x8140 from Shift JIS value + value -= 0x8140 + + // For characters with Shift JIS values from 0xE040 to 0xEBBF + } else if (value >= 0xE040 && value <= 0xEBBF) { + // Subtract 0xC140 from Shift JIS value + value -= 0xC140 + } else { + throw new Error( + 'Invalid SJIS character: ' + this.data[i] + '\n' + + 'Make sure your charset is UTF-8') + } + + // Multiply most significant byte of result by 0xC0 + // and add least significant byte to product + value = (((value >>> 8) & 0xff) * 0xC0) + (value & 0xff) + + // Convert result to a 13-bit binary string + bitBuffer.put(value, 13) + } +} + +module.exports = KanjiData diff --git a/node_modules/qrcode/lib/core/mask-pattern.js b/node_modules/qrcode/lib/core/mask-pattern.js new file mode 100644 index 0000000..f5f8900 --- /dev/null +++ b/node_modules/qrcode/lib/core/mask-pattern.js @@ -0,0 +1,234 @@ +/** + * Data mask pattern reference + * @type {Object} + */ +exports.Patterns = { + PATTERN000: 0, + PATTERN001: 1, + PATTERN010: 2, + PATTERN011: 3, + PATTERN100: 4, + PATTERN101: 5, + PATTERN110: 6, + PATTERN111: 7 +} + +/** + * Weighted penalty scores for the undesirable features + * @type {Object} + */ +const PenaltyScores = { + N1: 3, + N2: 3, + N3: 40, + N4: 10 +} + +/** + * Check if mask pattern value is valid + * + * @param {Number} mask Mask pattern + * @return {Boolean} true if valid, false otherwise + */ +exports.isValid = function isValid (mask) { + return mask != null && mask !== '' && !isNaN(mask) && mask >= 0 && mask <= 7 +} + +/** + * Returns mask pattern from a value. + * If value is not valid, returns undefined + * + * @param {Number|String} value Mask pattern value + * @return {Number} Valid mask pattern or undefined + */ +exports.from = function from (value) { + return exports.isValid(value) ? parseInt(value, 10) : undefined +} + +/** +* Find adjacent modules in row/column with the same color +* and assign a penalty value. +* +* Points: N1 + i +* i is the amount by which the number of adjacent modules of the same color exceeds 5 +*/ +exports.getPenaltyN1 = function getPenaltyN1 (data) { + const size = data.size + let points = 0 + let sameCountCol = 0 + let sameCountRow = 0 + let lastCol = null + let lastRow = null + + for (let row = 0; row < size; row++) { + sameCountCol = sameCountRow = 0 + lastCol = lastRow = null + + for (let col = 0; col < size; col++) { + let module = data.get(row, col) + if (module === lastCol) { + sameCountCol++ + } else { + if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5) + lastCol = module + sameCountCol = 1 + } + + module = data.get(col, row) + if (module === lastRow) { + sameCountRow++ + } else { + if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5) + lastRow = module + sameCountRow = 1 + } + } + + if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5) + if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5) + } + + return points +} + +/** + * Find 2x2 blocks with the same color and assign a penalty value + * + * Points: N2 * (m - 1) * (n - 1) + */ +exports.getPenaltyN2 = function getPenaltyN2 (data) { + const size = data.size + let points = 0 + + for (let row = 0; row < size - 1; row++) { + for (let col = 0; col < size - 1; col++) { + const last = data.get(row, col) + + data.get(row, col + 1) + + data.get(row + 1, col) + + data.get(row + 1, col + 1) + + if (last === 4 || last === 0) points++ + } + } + + return points * PenaltyScores.N2 +} + +/** + * Find 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column, + * preceded or followed by light area 4 modules wide + * + * Points: N3 * number of pattern found + */ +exports.getPenaltyN3 = function getPenaltyN3 (data) { + const size = data.size + let points = 0 + let bitsCol = 0 + let bitsRow = 0 + + for (let row = 0; row < size; row++) { + bitsCol = bitsRow = 0 + for (let col = 0; col < size; col++) { + bitsCol = ((bitsCol << 1) & 0x7FF) | data.get(row, col) + if (col >= 10 && (bitsCol === 0x5D0 || bitsCol === 0x05D)) points++ + + bitsRow = ((bitsRow << 1) & 0x7FF) | data.get(col, row) + if (col >= 10 && (bitsRow === 0x5D0 || bitsRow === 0x05D)) points++ + } + } + + return points * PenaltyScores.N3 +} + +/** + * Calculate proportion of dark modules in entire symbol + * + * Points: N4 * k + * + * k is the rating of the deviation of the proportion of dark modules + * in the symbol from 50% in steps of 5% + */ +exports.getPenaltyN4 = function getPenaltyN4 (data) { + let darkCount = 0 + const modulesCount = data.data.length + + for (let i = 0; i < modulesCount; i++) darkCount += data.data[i] + + const k = Math.abs(Math.ceil((darkCount * 100 / modulesCount) / 5) - 10) + + return k * PenaltyScores.N4 +} + +/** + * Return mask value at given position + * + * @param {Number} maskPattern Pattern reference value + * @param {Number} i Row + * @param {Number} j Column + * @return {Boolean} Mask value + */ +function getMaskAt (maskPattern, i, j) { + switch (maskPattern) { + case exports.Patterns.PATTERN000: return (i + j) % 2 === 0 + case exports.Patterns.PATTERN001: return i % 2 === 0 + case exports.Patterns.PATTERN010: return j % 3 === 0 + case exports.Patterns.PATTERN011: return (i + j) % 3 === 0 + case exports.Patterns.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0 + case exports.Patterns.PATTERN101: return (i * j) % 2 + (i * j) % 3 === 0 + case exports.Patterns.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 === 0 + case exports.Patterns.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 === 0 + + default: throw new Error('bad maskPattern:' + maskPattern) + } +} + +/** + * Apply a mask pattern to a BitMatrix + * + * @param {Number} pattern Pattern reference number + * @param {BitMatrix} data BitMatrix data + */ +exports.applyMask = function applyMask (pattern, data) { + const size = data.size + + for (let col = 0; col < size; col++) { + for (let row = 0; row < size; row++) { + if (data.isReserved(row, col)) continue + data.xor(row, col, getMaskAt(pattern, row, col)) + } + } +} + +/** + * Returns the best mask pattern for data + * + * @param {BitMatrix} data + * @return {Number} Mask pattern reference number + */ +exports.getBestMask = function getBestMask (data, setupFormatFunc) { + const numPatterns = Object.keys(exports.Patterns).length + let bestPattern = 0 + let lowerPenalty = Infinity + + for (let p = 0; p < numPatterns; p++) { + setupFormatFunc(p) + exports.applyMask(p, data) + + // Calculate penalty + const penalty = + exports.getPenaltyN1(data) + + exports.getPenaltyN2(data) + + exports.getPenaltyN3(data) + + exports.getPenaltyN4(data) + + // Undo previously applied mask + exports.applyMask(p, data) + + if (penalty < lowerPenalty) { + lowerPenalty = penalty + bestPattern = p + } + } + + return bestPattern +} diff --git a/node_modules/qrcode/lib/core/mode.js b/node_modules/qrcode/lib/core/mode.js new file mode 100644 index 0000000..fd95a6e --- /dev/null +++ b/node_modules/qrcode/lib/core/mode.js @@ -0,0 +1,167 @@ +const VersionCheck = require('./version-check') +const Regex = require('./regex') + +/** + * Numeric mode encodes data from the decimal digit set (0 - 9) + * (byte values 30HEX to 39HEX). + * Normally, 3 data characters are represented by 10 bits. + * + * @type {Object} + */ +exports.NUMERIC = { + id: 'Numeric', + bit: 1 << 0, + ccBits: [10, 12, 14] +} + +/** + * Alphanumeric mode encodes data from a set of 45 characters, + * i.e. 10 numeric digits (0 - 9), + * 26 alphabetic characters (A - Z), + * and 9 symbols (SP, $, %, *, +, -, ., /, :). + * Normally, two input characters are represented by 11 bits. + * + * @type {Object} + */ +exports.ALPHANUMERIC = { + id: 'Alphanumeric', + bit: 1 << 1, + ccBits: [9, 11, 13] +} + +/** + * In byte mode, data is encoded at 8 bits per character. + * + * @type {Object} + */ +exports.BYTE = { + id: 'Byte', + bit: 1 << 2, + ccBits: [8, 16, 16] +} + +/** + * The Kanji mode efficiently encodes Kanji characters in accordance with + * the Shift JIS system based on JIS X 0208. + * The Shift JIS values are shifted from the JIS X 0208 values. + * JIS X 0208 gives details of the shift coded representation. + * Each two-byte character value is compacted to a 13-bit binary codeword. + * + * @type {Object} + */ +exports.KANJI = { + id: 'Kanji', + bit: 1 << 3, + ccBits: [8, 10, 12] +} + +/** + * Mixed mode will contain a sequences of data in a combination of any of + * the modes described above + * + * @type {Object} + */ +exports.MIXED = { + bit: -1 +} + +/** + * Returns the number of bits needed to store the data length + * according to QR Code specifications. + * + * @param {Mode} mode Data mode + * @param {Number} version QR Code version + * @return {Number} Number of bits + */ +exports.getCharCountIndicator = function getCharCountIndicator (mode, version) { + if (!mode.ccBits) throw new Error('Invalid mode: ' + mode) + + if (!VersionCheck.isValid(version)) { + throw new Error('Invalid version: ' + version) + } + + if (version >= 1 && version < 10) return mode.ccBits[0] + else if (version < 27) return mode.ccBits[1] + return mode.ccBits[2] +} + +/** + * Returns the most efficient mode to store the specified data + * + * @param {String} dataStr Input data string + * @return {Mode} Best mode + */ +exports.getBestModeForData = function getBestModeForData (dataStr) { + if (Regex.testNumeric(dataStr)) return exports.NUMERIC + else if (Regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC + else if (Regex.testKanji(dataStr)) return exports.KANJI + else return exports.BYTE +} + +/** + * Return mode name as string + * + * @param {Mode} mode Mode object + * @returns {String} Mode name + */ +exports.toString = function toString (mode) { + if (mode && mode.id) return mode.id + throw new Error('Invalid mode') +} + +/** + * Check if input param is a valid mode object + * + * @param {Mode} mode Mode object + * @returns {Boolean} True if valid mode, false otherwise + */ +exports.isValid = function isValid (mode) { + return mode && mode.bit && mode.ccBits +} + +/** + * Get mode object from its name + * + * @param {String} string Mode name + * @returns {Mode} Mode object + */ +function fromString (string) { + if (typeof string !== 'string') { + throw new Error('Param is not a string') + } + + const lcStr = string.toLowerCase() + + switch (lcStr) { + case 'numeric': + return exports.NUMERIC + case 'alphanumeric': + return exports.ALPHANUMERIC + case 'kanji': + return exports.KANJI + case 'byte': + return exports.BYTE + default: + throw new Error('Unknown mode: ' + string) + } +} + +/** + * Returns mode from a value. + * If value is not a valid mode, returns defaultValue + * + * @param {Mode|String} value Encoding mode + * @param {Mode} defaultValue Fallback value + * @return {Mode} Encoding mode + */ +exports.from = function from (value, defaultValue) { + if (exports.isValid(value)) { + return value + } + + try { + return fromString(value) + } catch (e) { + return defaultValue + } +} diff --git a/node_modules/qrcode/lib/core/numeric-data.js b/node_modules/qrcode/lib/core/numeric-data.js new file mode 100644 index 0000000..5223991 --- /dev/null +++ b/node_modules/qrcode/lib/core/numeric-data.js @@ -0,0 +1,43 @@ +const Mode = require('./mode') + +function NumericData (data) { + this.mode = Mode.NUMERIC + this.data = data.toString() +} + +NumericData.getBitsLength = function getBitsLength (length) { + return 10 * Math.floor(length / 3) + ((length % 3) ? ((length % 3) * 3 + 1) : 0) +} + +NumericData.prototype.getLength = function getLength () { + return this.data.length +} + +NumericData.prototype.getBitsLength = function getBitsLength () { + return NumericData.getBitsLength(this.data.length) +} + +NumericData.prototype.write = function write (bitBuffer) { + let i, group, value + + // The input data string is divided into groups of three digits, + // and each group is converted to its 10-bit binary equivalent. + for (i = 0; i + 3 <= this.data.length; i += 3) { + group = this.data.substr(i, 3) + value = parseInt(group, 10) + + bitBuffer.put(value, 10) + } + + // If the number of input digits is not an exact multiple of three, + // the final one or two digits are converted to 4 or 7 bits respectively. + const remainingNum = this.data.length - i + if (remainingNum > 0) { + group = this.data.substr(i) + value = parseInt(group, 10) + + bitBuffer.put(value, remainingNum * 3 + 1) + } +} + +module.exports = NumericData diff --git a/node_modules/qrcode/lib/core/polynomial.js b/node_modules/qrcode/lib/core/polynomial.js new file mode 100644 index 0000000..c6ed9c2 --- /dev/null +++ b/node_modules/qrcode/lib/core/polynomial.js @@ -0,0 +1,62 @@ +const GF = require('./galois-field') + +/** + * Multiplies two polynomials inside Galois Field + * + * @param {Uint8Array} p1 Polynomial + * @param {Uint8Array} p2 Polynomial + * @return {Uint8Array} Product of p1 and p2 + */ +exports.mul = function mul (p1, p2) { + const coeff = new Uint8Array(p1.length + p2.length - 1) + + for (let i = 0; i < p1.length; i++) { + for (let j = 0; j < p2.length; j++) { + coeff[i + j] ^= GF.mul(p1[i], p2[j]) + } + } + + return coeff +} + +/** + * Calculate the remainder of polynomials division + * + * @param {Uint8Array} divident Polynomial + * @param {Uint8Array} divisor Polynomial + * @return {Uint8Array} Remainder + */ +exports.mod = function mod (divident, divisor) { + let result = new Uint8Array(divident) + + while ((result.length - divisor.length) >= 0) { + const coeff = result[0] + + for (let i = 0; i < divisor.length; i++) { + result[i] ^= GF.mul(divisor[i], coeff) + } + + // remove all zeros from buffer head + let offset = 0 + while (offset < result.length && result[offset] === 0) offset++ + result = result.slice(offset) + } + + return result +} + +/** + * Generate an irreducible generator polynomial of specified degree + * (used by Reed-Solomon encoder) + * + * @param {Number} degree Degree of the generator polynomial + * @return {Uint8Array} Buffer containing polynomial coefficients + */ +exports.generateECPolynomial = function generateECPolynomial (degree) { + let poly = new Uint8Array([1]) + for (let i = 0; i < degree; i++) { + poly = exports.mul(poly, new Uint8Array([1, GF.exp(i)])) + } + + return poly +} diff --git a/node_modules/qrcode/lib/core/qrcode.js b/node_modules/qrcode/lib/core/qrcode.js new file mode 100644 index 0000000..f76df54 --- /dev/null +++ b/node_modules/qrcode/lib/core/qrcode.js @@ -0,0 +1,495 @@ +const Utils = require('./utils') +const ECLevel = require('./error-correction-level') +const BitBuffer = require('./bit-buffer') +const BitMatrix = require('./bit-matrix') +const AlignmentPattern = require('./alignment-pattern') +const FinderPattern = require('./finder-pattern') +const MaskPattern = require('./mask-pattern') +const ECCode = require('./error-correction-code') +const ReedSolomonEncoder = require('./reed-solomon-encoder') +const Version = require('./version') +const FormatInfo = require('./format-info') +const Mode = require('./mode') +const Segments = require('./segments') + +/** + * QRCode for JavaScript + * + * modified by Ryan Day for nodejs support + * Copyright (c) 2011 Ryan Day + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + * +//--------------------------------------------------------------------- +// QRCode for JavaScript +// +// Copyright (c) 2009 Kazuhiko Arase +// +// URL: http://www.d-project.com/ +// +// Licensed under the MIT license: +// http://www.opensource.org/licenses/mit-license.php +// +// The word "QR Code" is registered trademark of +// DENSO WAVE INCORPORATED +// http://www.denso-wave.com/qrcode/faqpatent-e.html +// +//--------------------------------------------------------------------- +*/ + +/** + * Add finder patterns bits to matrix + * + * @param {BitMatrix} matrix Modules matrix + * @param {Number} version QR Code version + */ +function setupFinderPattern (matrix, version) { + const size = matrix.size + const pos = FinderPattern.getPositions(version) + + for (let i = 0; i < pos.length; i++) { + const row = pos[i][0] + const col = pos[i][1] + + for (let r = -1; r <= 7; r++) { + if (row + r <= -1 || size <= row + r) continue + + for (let c = -1; c <= 7; c++) { + if (col + c <= -1 || size <= col + c) continue + + if ((r >= 0 && r <= 6 && (c === 0 || c === 6)) || + (c >= 0 && c <= 6 && (r === 0 || r === 6)) || + (r >= 2 && r <= 4 && c >= 2 && c <= 4)) { + matrix.set(row + r, col + c, true, true) + } else { + matrix.set(row + r, col + c, false, true) + } + } + } + } +} + +/** + * Add timing pattern bits to matrix + * + * Note: this function must be called before {@link setupAlignmentPattern} + * + * @param {BitMatrix} matrix Modules matrix + */ +function setupTimingPattern (matrix) { + const size = matrix.size + + for (let r = 8; r < size - 8; r++) { + const value = r % 2 === 0 + matrix.set(r, 6, value, true) + matrix.set(6, r, value, true) + } +} + +/** + * Add alignment patterns bits to matrix + * + * Note: this function must be called after {@link setupTimingPattern} + * + * @param {BitMatrix} matrix Modules matrix + * @param {Number} version QR Code version + */ +function setupAlignmentPattern (matrix, version) { + const pos = AlignmentPattern.getPositions(version) + + for (let i = 0; i < pos.length; i++) { + const row = pos[i][0] + const col = pos[i][1] + + for (let r = -2; r <= 2; r++) { + for (let c = -2; c <= 2; c++) { + if (r === -2 || r === 2 || c === -2 || c === 2 || + (r === 0 && c === 0)) { + matrix.set(row + r, col + c, true, true) + } else { + matrix.set(row + r, col + c, false, true) + } + } + } + } +} + +/** + * Add version info bits to matrix + * + * @param {BitMatrix} matrix Modules matrix + * @param {Number} version QR Code version + */ +function setupVersionInfo (matrix, version) { + const size = matrix.size + const bits = Version.getEncodedBits(version) + let row, col, mod + + for (let i = 0; i < 18; i++) { + row = Math.floor(i / 3) + col = i % 3 + size - 8 - 3 + mod = ((bits >> i) & 1) === 1 + + matrix.set(row, col, mod, true) + matrix.set(col, row, mod, true) + } +} + +/** + * Add format info bits to matrix + * + * @param {BitMatrix} matrix Modules matrix + * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level + * @param {Number} maskPattern Mask pattern reference value + */ +function setupFormatInfo (matrix, errorCorrectionLevel, maskPattern) { + const size = matrix.size + const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern) + let i, mod + + for (i = 0; i < 15; i++) { + mod = ((bits >> i) & 1) === 1 + + // vertical + if (i < 6) { + matrix.set(i, 8, mod, true) + } else if (i < 8) { + matrix.set(i + 1, 8, mod, true) + } else { + matrix.set(size - 15 + i, 8, mod, true) + } + + // horizontal + if (i < 8) { + matrix.set(8, size - i - 1, mod, true) + } else if (i < 9) { + matrix.set(8, 15 - i - 1 + 1, mod, true) + } else { + matrix.set(8, 15 - i - 1, mod, true) + } + } + + // fixed module + matrix.set(size - 8, 8, 1, true) +} + +/** + * Add encoded data bits to matrix + * + * @param {BitMatrix} matrix Modules matrix + * @param {Uint8Array} data Data codewords + */ +function setupData (matrix, data) { + const size = matrix.size + let inc = -1 + let row = size - 1 + let bitIndex = 7 + let byteIndex = 0 + + for (let col = size - 1; col > 0; col -= 2) { + if (col === 6) col-- + + while (true) { + for (let c = 0; c < 2; c++) { + if (!matrix.isReserved(row, col - c)) { + let dark = false + + if (byteIndex < data.length) { + dark = (((data[byteIndex] >>> bitIndex) & 1) === 1) + } + + matrix.set(row, col - c, dark) + bitIndex-- + + if (bitIndex === -1) { + byteIndex++ + bitIndex = 7 + } + } + } + + row += inc + + if (row < 0 || size <= row) { + row -= inc + inc = -inc + break + } + } + } +} + +/** + * Create encoded codewords from data input + * + * @param {Number} version QR Code version + * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level + * @param {ByteData} data Data input + * @return {Uint8Array} Buffer containing encoded codewords + */ +function createData (version, errorCorrectionLevel, segments) { + // Prepare data buffer + const buffer = new BitBuffer() + + segments.forEach(function (data) { + // prefix data with mode indicator (4 bits) + buffer.put(data.mode.bit, 4) + + // Prefix data with character count indicator. + // The character count indicator is a string of bits that represents the + // number of characters that are being encoded. + // The character count indicator must be placed after the mode indicator + // and must be a certain number of bits long, depending on the QR version + // and data mode + // @see {@link Mode.getCharCountIndicator}. + buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version)) + + // add binary data sequence to buffer + data.write(buffer) + }) + + // Calculate required number of bits + const totalCodewords = Utils.getSymbolTotalCodewords(version) + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel) + const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8 + + // Add a terminator. + // If the bit string is shorter than the total number of required bits, + // a terminator of up to four 0s must be added to the right side of the string. + // If the bit string is more than four bits shorter than the required number of bits, + // add four 0s to the end. + if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) { + buffer.put(0, 4) + } + + // If the bit string is fewer than four bits shorter, add only the number of 0s that + // are needed to reach the required number of bits. + + // After adding the terminator, if the number of bits in the string is not a multiple of 8, + // pad the string on the right with 0s to make the string's length a multiple of 8. + while (buffer.getLengthInBits() % 8 !== 0) { + buffer.putBit(0) + } + + // Add pad bytes if the string is still shorter than the total number of required bits. + // Extend the buffer to fill the data capacity of the symbol corresponding to + // the Version and Error Correction Level by adding the Pad Codewords 11101100 (0xEC) + // and 00010001 (0x11) alternately. + const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8 + for (let i = 0; i < remainingByte; i++) { + buffer.put(i % 2 ? 0x11 : 0xEC, 8) + } + + return createCodewords(buffer, version, errorCorrectionLevel) +} + +/** + * Encode input data with Reed-Solomon and return codewords with + * relative error correction bits + * + * @param {BitBuffer} bitBuffer Data to encode + * @param {Number} version QR Code version + * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level + * @return {Uint8Array} Buffer containing encoded codewords + */ +function createCodewords (bitBuffer, version, errorCorrectionLevel) { + // Total codewords for this QR code version (Data + Error correction) + const totalCodewords = Utils.getSymbolTotalCodewords(version) + + // Total number of error correction codewords + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel) + + // Total number of data codewords + const dataTotalCodewords = totalCodewords - ecTotalCodewords + + // Total number of blocks + const ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel) + + // Calculate how many blocks each group should contain + const blocksInGroup2 = totalCodewords % ecTotalBlocks + const blocksInGroup1 = ecTotalBlocks - blocksInGroup2 + + const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks) + + const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks) + const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1 + + // Number of EC codewords is the same for both groups + const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1 + + // Initialize a Reed-Solomon encoder with a generator polynomial of degree ecCount + const rs = new ReedSolomonEncoder(ecCount) + + let offset = 0 + const dcData = new Array(ecTotalBlocks) + const ecData = new Array(ecTotalBlocks) + let maxDataSize = 0 + const buffer = new Uint8Array(bitBuffer.buffer) + + // Divide the buffer into the required number of blocks + for (let b = 0; b < ecTotalBlocks; b++) { + const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2 + + // extract a block of data from buffer + dcData[b] = buffer.slice(offset, offset + dataSize) + + // Calculate EC codewords for this data block + ecData[b] = rs.encode(dcData[b]) + + offset += dataSize + maxDataSize = Math.max(maxDataSize, dataSize) + } + + // Create final data + // Interleave the data and error correction codewords from each block + const data = new Uint8Array(totalCodewords) + let index = 0 + let i, r + + // Add data codewords + for (i = 0; i < maxDataSize; i++) { + for (r = 0; r < ecTotalBlocks; r++) { + if (i < dcData[r].length) { + data[index++] = dcData[r][i] + } + } + } + + // Apped EC codewords + for (i = 0; i < ecCount; i++) { + for (r = 0; r < ecTotalBlocks; r++) { + data[index++] = ecData[r][i] + } + } + + return data +} + +/** + * Build QR Code symbol + * + * @param {String} data Input string + * @param {Number} version QR Code version + * @param {ErrorCorretionLevel} errorCorrectionLevel Error level + * @param {MaskPattern} maskPattern Mask pattern + * @return {Object} Object containing symbol data + */ +function createSymbol (data, version, errorCorrectionLevel, maskPattern) { + let segments + + if (Array.isArray(data)) { + segments = Segments.fromArray(data) + } else if (typeof data === 'string') { + let estimatedVersion = version + + if (!estimatedVersion) { + const rawSegments = Segments.rawSplit(data) + + // Estimate best version that can contain raw splitted segments + estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel) + } + + // Build optimized segments + // If estimated version is undefined, try with the highest version + segments = Segments.fromString(data, estimatedVersion || 40) + } else { + throw new Error('Invalid data') + } + + // Get the min version that can contain data + const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel) + + // If no version is found, data cannot be stored + if (!bestVersion) { + throw new Error('The amount of data is too big to be stored in a QR Code') + } + + // If not specified, use min version as default + if (!version) { + version = bestVersion + + // Check if the specified version can contain the data + } else if (version < bestVersion) { + throw new Error('\n' + + 'The chosen QR Code version cannot contain this amount of data.\n' + + 'Minimum version required to store current data is: ' + bestVersion + '.\n' + ) + } + + const dataBits = createData(version, errorCorrectionLevel, segments) + + // Allocate matrix buffer + const moduleCount = Utils.getSymbolSize(version) + const modules = new BitMatrix(moduleCount) + + // Add function modules + setupFinderPattern(modules, version) + setupTimingPattern(modules) + setupAlignmentPattern(modules, version) + + // Add temporary dummy bits for format info just to set them as reserved. + // This is needed to prevent these bits from being masked by {@link MaskPattern.applyMask} + // since the masking operation must be performed only on the encoding region. + // These blocks will be replaced with correct values later in code. + setupFormatInfo(modules, errorCorrectionLevel, 0) + + if (version >= 7) { + setupVersionInfo(modules, version) + } + + // Add data codewords + setupData(modules, dataBits) + + if (isNaN(maskPattern)) { + // Find best mask pattern + maskPattern = MaskPattern.getBestMask(modules, + setupFormatInfo.bind(null, modules, errorCorrectionLevel)) + } + + // Apply mask pattern + MaskPattern.applyMask(maskPattern, modules) + + // Replace format info bits with correct values + setupFormatInfo(modules, errorCorrectionLevel, maskPattern) + + return { + modules: modules, + version: version, + errorCorrectionLevel: errorCorrectionLevel, + maskPattern: maskPattern, + segments: segments + } +} + +/** + * QR Code + * + * @param {String | Array} data Input data + * @param {Object} options Optional configurations + * @param {Number} options.version QR Code version + * @param {String} options.errorCorrectionLevel Error correction level + * @param {Function} options.toSJISFunc Helper func to convert utf8 to sjis + */ +exports.create = function create (data, options) { + if (typeof data === 'undefined' || data === '') { + throw new Error('No input text') + } + + let errorCorrectionLevel = ECLevel.M + let version + let mask + + if (typeof options !== 'undefined') { + // Use higher error correction level as default + errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M) + version = Version.from(options.version) + mask = MaskPattern.from(options.maskPattern) + + if (options.toSJISFunc) { + Utils.setToSJISFunction(options.toSJISFunc) + } + } + + return createSymbol(data, version, errorCorrectionLevel, mask) +} diff --git a/node_modules/qrcode/lib/core/reed-solomon-encoder.js b/node_modules/qrcode/lib/core/reed-solomon-encoder.js new file mode 100644 index 0000000..c198422 --- /dev/null +++ b/node_modules/qrcode/lib/core/reed-solomon-encoder.js @@ -0,0 +1,56 @@ +const Polynomial = require('./polynomial') + +function ReedSolomonEncoder (degree) { + this.genPoly = undefined + this.degree = degree + + if (this.degree) this.initialize(this.degree) +} + +/** + * Initialize the encoder. + * The input param should correspond to the number of error correction codewords. + * + * @param {Number} degree + */ +ReedSolomonEncoder.prototype.initialize = function initialize (degree) { + // create an irreducible generator polynomial + this.degree = degree + this.genPoly = Polynomial.generateECPolynomial(this.degree) +} + +/** + * Encodes a chunk of data + * + * @param {Uint8Array} data Buffer containing input data + * @return {Uint8Array} Buffer containing encoded data + */ +ReedSolomonEncoder.prototype.encode = function encode (data) { + if (!this.genPoly) { + throw new Error('Encoder not initialized') + } + + // Calculate EC for this data block + // extends data size to data+genPoly size + const paddedData = new Uint8Array(data.length + this.degree) + paddedData.set(data) + + // The error correction codewords are the remainder after dividing the data codewords + // by a generator polynomial + const remainder = Polynomial.mod(paddedData, this.genPoly) + + // return EC data blocks (last n byte, where n is the degree of genPoly) + // If coefficients number in remainder are less than genPoly degree, + // pad with 0s to the left to reach the needed number of coefficients + const start = this.degree - remainder.length + if (start > 0) { + const buff = new Uint8Array(this.degree) + buff.set(remainder, start) + + return buff + } + + return remainder +} + +module.exports = ReedSolomonEncoder diff --git a/node_modules/qrcode/lib/core/regex.js b/node_modules/qrcode/lib/core/regex.js new file mode 100644 index 0000000..9dd13a4 --- /dev/null +++ b/node_modules/qrcode/lib/core/regex.js @@ -0,0 +1,31 @@ +const numeric = '[0-9]+' +const alphanumeric = '[A-Z $%*+\\-./:]+' +let kanji = '(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|' + + '[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|' + + '[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|' + + '[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+' +kanji = kanji.replace(/u/g, '\\u') + +const byte = '(?:(?![A-Z0-9 $%*+\\-./:]|' + kanji + ')(?:.|[\r\n]))+' + +exports.KANJI = new RegExp(kanji, 'g') +exports.BYTE_KANJI = new RegExp('[^A-Z0-9 $%*+\\-./:]+', 'g') +exports.BYTE = new RegExp(byte, 'g') +exports.NUMERIC = new RegExp(numeric, 'g') +exports.ALPHANUMERIC = new RegExp(alphanumeric, 'g') + +const TEST_KANJI = new RegExp('^' + kanji + '$') +const TEST_NUMERIC = new RegExp('^' + numeric + '$') +const TEST_ALPHANUMERIC = new RegExp('^[A-Z0-9 $%*+\\-./:]+$') + +exports.testKanji = function testKanji (str) { + return TEST_KANJI.test(str) +} + +exports.testNumeric = function testNumeric (str) { + return TEST_NUMERIC.test(str) +} + +exports.testAlphanumeric = function testAlphanumeric (str) { + return TEST_ALPHANUMERIC.test(str) +} diff --git a/node_modules/qrcode/lib/core/segments.js b/node_modules/qrcode/lib/core/segments.js new file mode 100644 index 0000000..ba8be17 --- /dev/null +++ b/node_modules/qrcode/lib/core/segments.js @@ -0,0 +1,330 @@ +const Mode = require('./mode') +const NumericData = require('./numeric-data') +const AlphanumericData = require('./alphanumeric-data') +const ByteData = require('./byte-data') +const KanjiData = require('./kanji-data') +const Regex = require('./regex') +const Utils = require('./utils') +const dijkstra = require('dijkstrajs') + +/** + * Returns UTF8 byte length + * + * @param {String} str Input string + * @return {Number} Number of byte + */ +function getStringByteLength (str) { + return unescape(encodeURIComponent(str)).length +} + +/** + * Get a list of segments of the specified mode + * from a string + * + * @param {Mode} mode Segment mode + * @param {String} str String to process + * @return {Array} Array of object with segments data + */ +function getSegments (regex, mode, str) { + const segments = [] + let result + + while ((result = regex.exec(str)) !== null) { + segments.push({ + data: result[0], + index: result.index, + mode: mode, + length: result[0].length + }) + } + + return segments +} + +/** + * Extracts a series of segments with the appropriate + * modes from a string + * + * @param {String} dataStr Input string + * @return {Array} Array of object with segments data + */ +function getSegmentsFromString (dataStr) { + const numSegs = getSegments(Regex.NUMERIC, Mode.NUMERIC, dataStr) + const alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode.ALPHANUMERIC, dataStr) + let byteSegs + let kanjiSegs + + if (Utils.isKanjiModeEnabled()) { + byteSegs = getSegments(Regex.BYTE, Mode.BYTE, dataStr) + kanjiSegs = getSegments(Regex.KANJI, Mode.KANJI, dataStr) + } else { + byteSegs = getSegments(Regex.BYTE_KANJI, Mode.BYTE, dataStr) + kanjiSegs = [] + } + + const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs) + + return segs + .sort(function (s1, s2) { + return s1.index - s2.index + }) + .map(function (obj) { + return { + data: obj.data, + mode: obj.mode, + length: obj.length + } + }) +} + +/** + * Returns how many bits are needed to encode a string of + * specified length with the specified mode + * + * @param {Number} length String length + * @param {Mode} mode Segment mode + * @return {Number} Bit length + */ +function getSegmentBitsLength (length, mode) { + switch (mode) { + case Mode.NUMERIC: + return NumericData.getBitsLength(length) + case Mode.ALPHANUMERIC: + return AlphanumericData.getBitsLength(length) + case Mode.KANJI: + return KanjiData.getBitsLength(length) + case Mode.BYTE: + return ByteData.getBitsLength(length) + } +} + +/** + * Merges adjacent segments which have the same mode + * + * @param {Array} segs Array of object with segments data + * @return {Array} Array of object with segments data + */ +function mergeSegments (segs) { + return segs.reduce(function (acc, curr) { + const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null + if (prevSeg && prevSeg.mode === curr.mode) { + acc[acc.length - 1].data += curr.data + return acc + } + + acc.push(curr) + return acc + }, []) +} + +/** + * Generates a list of all possible nodes combination which + * will be used to build a segments graph. + * + * Nodes are divided by groups. Each group will contain a list of all the modes + * in which is possible to encode the given text. + * + * For example the text '12345' can be encoded as Numeric, Alphanumeric or Byte. + * The group for '12345' will contain then 3 objects, one for each + * possible encoding mode. + * + * Each node represents a possible segment. + * + * @param {Array} segs Array of object with segments data + * @return {Array} Array of object with segments data + */ +function buildNodes (segs) { + const nodes = [] + for (let i = 0; i < segs.length; i++) { + const seg = segs[i] + + switch (seg.mode) { + case Mode.NUMERIC: + nodes.push([seg, + { data: seg.data, mode: Mode.ALPHANUMERIC, length: seg.length }, + { data: seg.data, mode: Mode.BYTE, length: seg.length } + ]) + break + case Mode.ALPHANUMERIC: + nodes.push([seg, + { data: seg.data, mode: Mode.BYTE, length: seg.length } + ]) + break + case Mode.KANJI: + nodes.push([seg, + { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) } + ]) + break + case Mode.BYTE: + nodes.push([ + { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) } + ]) + } + } + + return nodes +} + +/** + * Builds a graph from a list of nodes. + * All segments in each node group will be connected with all the segments of + * the next group and so on. + * + * At each connection will be assigned a weight depending on the + * segment's byte length. + * + * @param {Array} nodes Array of object with segments data + * @param {Number} version QR Code version + * @return {Object} Graph of all possible segments + */ +function buildGraph (nodes, version) { + const table = {} + const graph = { start: {} } + let prevNodeIds = ['start'] + + for (let i = 0; i < nodes.length; i++) { + const nodeGroup = nodes[i] + const currentNodeIds = [] + + for (let j = 0; j < nodeGroup.length; j++) { + const node = nodeGroup[j] + const key = '' + i + j + + currentNodeIds.push(key) + table[key] = { node: node, lastCount: 0 } + graph[key] = {} + + for (let n = 0; n < prevNodeIds.length; n++) { + const prevNodeId = prevNodeIds[n] + + if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) { + graph[prevNodeId][key] = + getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) - + getSegmentBitsLength(table[prevNodeId].lastCount, node.mode) + + table[prevNodeId].lastCount += node.length + } else { + if (table[prevNodeId]) table[prevNodeId].lastCount = node.length + + graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) + + 4 + Mode.getCharCountIndicator(node.mode, version) // switch cost + } + } + } + + prevNodeIds = currentNodeIds + } + + for (let n = 0; n < prevNodeIds.length; n++) { + graph[prevNodeIds[n]].end = 0 + } + + return { map: graph, table: table } +} + +/** + * Builds a segment from a specified data and mode. + * If a mode is not specified, the more suitable will be used. + * + * @param {String} data Input data + * @param {Mode | String} modesHint Data mode + * @return {Segment} Segment + */ +function buildSingleSegment (data, modesHint) { + let mode + const bestMode = Mode.getBestModeForData(data) + + mode = Mode.from(modesHint, bestMode) + + // Make sure data can be encoded + if (mode !== Mode.BYTE && mode.bit < bestMode.bit) { + throw new Error('"' + data + '"' + + ' cannot be encoded with mode ' + Mode.toString(mode) + + '.\n Suggested mode is: ' + Mode.toString(bestMode)) + } + + // Use Mode.BYTE if Kanji support is disabled + if (mode === Mode.KANJI && !Utils.isKanjiModeEnabled()) { + mode = Mode.BYTE + } + + switch (mode) { + case Mode.NUMERIC: + return new NumericData(data) + + case Mode.ALPHANUMERIC: + return new AlphanumericData(data) + + case Mode.KANJI: + return new KanjiData(data) + + case Mode.BYTE: + return new ByteData(data) + } +} + +/** + * Builds a list of segments from an array. + * Array can contain Strings or Objects with segment's info. + * + * For each item which is a string, will be generated a segment with the given + * string and the more appropriate encoding mode. + * + * For each item which is an object, will be generated a segment with the given + * data and mode. + * Objects must contain at least the property "data". + * If property "mode" is not present, the more suitable mode will be used. + * + * @param {Array} array Array of objects with segments data + * @return {Array} Array of Segments + */ +exports.fromArray = function fromArray (array) { + return array.reduce(function (acc, seg) { + if (typeof seg === 'string') { + acc.push(buildSingleSegment(seg, null)) + } else if (seg.data) { + acc.push(buildSingleSegment(seg.data, seg.mode)) + } + + return acc + }, []) +} + +/** + * Builds an optimized sequence of segments from a string, + * which will produce the shortest possible bitstream. + * + * @param {String} data Input string + * @param {Number} version QR Code version + * @return {Array} Array of segments + */ +exports.fromString = function fromString (data, version) { + const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled()) + + const nodes = buildNodes(segs) + const graph = buildGraph(nodes, version) + const path = dijkstra.find_path(graph.map, 'start', 'end') + + const optimizedSegs = [] + for (let i = 1; i < path.length - 1; i++) { + optimizedSegs.push(graph.table[path[i]].node) + } + + return exports.fromArray(mergeSegments(optimizedSegs)) +} + +/** + * Splits a string in various segments with the modes which + * best represent their content. + * The produced segments are far from being optimized. + * The output of this function is only used to estimate a QR Code version + * which may contain the data. + * + * @param {string} data Input string + * @return {Array} Array of segments + */ +exports.rawSplit = function rawSplit (data) { + return exports.fromArray( + getSegmentsFromString(data, Utils.isKanjiModeEnabled()) + ) +} diff --git a/node_modules/qrcode/lib/core/utils.js b/node_modules/qrcode/lib/core/utils.js new file mode 100644 index 0000000..8a0b87b --- /dev/null +++ b/node_modules/qrcode/lib/core/utils.js @@ -0,0 +1,63 @@ +let toSJISFunction +const CODEWORDS_COUNT = [ + 0, // Not used + 26, 44, 70, 100, 134, 172, 196, 242, 292, 346, + 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085, + 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185, + 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706 +] + +/** + * Returns the QR Code size for the specified version + * + * @param {Number} version QR Code version + * @return {Number} size of QR code + */ +exports.getSymbolSize = function getSymbolSize (version) { + if (!version) throw new Error('"version" cannot be null or undefined') + if (version < 1 || version > 40) throw new Error('"version" should be in range from 1 to 40') + return version * 4 + 17 +} + +/** + * Returns the total number of codewords used to store data and EC information. + * + * @param {Number} version QR Code version + * @return {Number} Data length in bits + */ +exports.getSymbolTotalCodewords = function getSymbolTotalCodewords (version) { + return CODEWORDS_COUNT[version] +} + +/** + * Encode data with Bose-Chaudhuri-Hocquenghem + * + * @param {Number} data Value to encode + * @return {Number} Encoded value + */ +exports.getBCHDigit = function (data) { + let digit = 0 + + while (data !== 0) { + digit++ + data >>>= 1 + } + + return digit +} + +exports.setToSJISFunction = function setToSJISFunction (f) { + if (typeof f !== 'function') { + throw new Error('"toSJISFunc" is not a valid function.') + } + + toSJISFunction = f +} + +exports.isKanjiModeEnabled = function () { + return typeof toSJISFunction !== 'undefined' +} + +exports.toSJIS = function toSJIS (kanji) { + return toSJISFunction(kanji) +} diff --git a/node_modules/qrcode/lib/core/version-check.js b/node_modules/qrcode/lib/core/version-check.js new file mode 100644 index 0000000..dd32b5a --- /dev/null +++ b/node_modules/qrcode/lib/core/version-check.js @@ -0,0 +1,9 @@ +/** + * Check if QR Code version is valid + * + * @param {Number} version QR Code version + * @return {Boolean} true if valid version, false otherwise + */ +exports.isValid = function isValid (version) { + return !isNaN(version) && version >= 1 && version <= 40 +} diff --git a/node_modules/qrcode/lib/core/version.js b/node_modules/qrcode/lib/core/version.js new file mode 100644 index 0000000..32b8466 --- /dev/null +++ b/node_modules/qrcode/lib/core/version.js @@ -0,0 +1,163 @@ +const Utils = require('./utils') +const ECCode = require('./error-correction-code') +const ECLevel = require('./error-correction-level') +const Mode = require('./mode') +const VersionCheck = require('./version-check') + +// Generator polynomial used to encode version information +const G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0) +const G18_BCH = Utils.getBCHDigit(G18) + +function getBestVersionForDataLength (mode, length, errorCorrectionLevel) { + for (let currentVersion = 1; currentVersion <= 40; currentVersion++) { + if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) { + return currentVersion + } + } + + return undefined +} + +function getReservedBitsCount (mode, version) { + // Character count indicator + mode indicator bits + return Mode.getCharCountIndicator(mode, version) + 4 +} + +function getTotalBitsFromDataArray (segments, version) { + let totalBits = 0 + + segments.forEach(function (data) { + const reservedBits = getReservedBitsCount(data.mode, version) + totalBits += reservedBits + data.getBitsLength() + }) + + return totalBits +} + +function getBestVersionForMixedData (segments, errorCorrectionLevel) { + for (let currentVersion = 1; currentVersion <= 40; currentVersion++) { + const length = getTotalBitsFromDataArray(segments, currentVersion) + if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, Mode.MIXED)) { + return currentVersion + } + } + + return undefined +} + +/** + * Returns version number from a value. + * If value is not a valid version, returns defaultValue + * + * @param {Number|String} value QR Code version + * @param {Number} defaultValue Fallback value + * @return {Number} QR Code version number + */ +exports.from = function from (value, defaultValue) { + if (VersionCheck.isValid(value)) { + return parseInt(value, 10) + } + + return defaultValue +} + +/** + * Returns how much data can be stored with the specified QR code version + * and error correction level + * + * @param {Number} version QR Code version (1-40) + * @param {Number} errorCorrectionLevel Error correction level + * @param {Mode} mode Data mode + * @return {Number} Quantity of storable data + */ +exports.getCapacity = function getCapacity (version, errorCorrectionLevel, mode) { + if (!VersionCheck.isValid(version)) { + throw new Error('Invalid QR Code version') + } + + // Use Byte mode as default + if (typeof mode === 'undefined') mode = Mode.BYTE + + // Total codewords for this QR code version (Data + Error correction) + const totalCodewords = Utils.getSymbolTotalCodewords(version) + + // Total number of error correction codewords + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel) + + // Total number of data codewords + const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8 + + if (mode === Mode.MIXED) return dataTotalCodewordsBits + + const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode, version) + + // Return max number of storable codewords + switch (mode) { + case Mode.NUMERIC: + return Math.floor((usableBits / 10) * 3) + + case Mode.ALPHANUMERIC: + return Math.floor((usableBits / 11) * 2) + + case Mode.KANJI: + return Math.floor(usableBits / 13) + + case Mode.BYTE: + default: + return Math.floor(usableBits / 8) + } +} + +/** + * Returns the minimum version needed to contain the amount of data + * + * @param {Segment} data Segment of data + * @param {Number} [errorCorrectionLevel=H] Error correction level + * @param {Mode} mode Data mode + * @return {Number} QR Code version + */ +exports.getBestVersionForData = function getBestVersionForData (data, errorCorrectionLevel) { + let seg + + const ecl = ECLevel.from(errorCorrectionLevel, ECLevel.M) + + if (Array.isArray(data)) { + if (data.length > 1) { + return getBestVersionForMixedData(data, ecl) + } + + if (data.length === 0) { + return 1 + } + + seg = data[0] + } else { + seg = data + } + + return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl) +} + +/** + * Returns version information with relative error correction bits + * + * The version information is included in QR Code symbols of version 7 or larger. + * It consists of an 18-bit sequence containing 6 data bits, + * with 12 error correction bits calculated using the (18, 6) Golay code. + * + * @param {Number} version QR Code version + * @return {Number} Encoded version info bits + */ +exports.getEncodedBits = function getEncodedBits (version) { + if (!VersionCheck.isValid(version) || version < 7) { + throw new Error('Invalid QR Code version') + } + + let d = version << 12 + + while (Utils.getBCHDigit(d) - G18_BCH >= 0) { + d ^= (G18 << (Utils.getBCHDigit(d) - G18_BCH)) + } + + return (version << 12) | d +} diff --git a/node_modules/qrcode/lib/index.js b/node_modules/qrcode/lib/index.js new file mode 100644 index 0000000..57c8f70 --- /dev/null +++ b/node_modules/qrcode/lib/index.js @@ -0,0 +1,12 @@ +/* +*copyright Ryan Day 2012 +* +* Licensed under the MIT license: +* http://www.opensource.org/licenses/mit-license.php +* +* this is the main server side application file for node-qrcode. +* these exports use serverside canvas api methods for file IO and buffers +* +*/ + +module.exports = require('./server') diff --git a/node_modules/qrcode/lib/renderer/canvas.js b/node_modules/qrcode/lib/renderer/canvas.js new file mode 100644 index 0000000..42050cf --- /dev/null +++ b/node_modules/qrcode/lib/renderer/canvas.js @@ -0,0 +1,63 @@ +const Utils = require('./utils') + +function clearCanvas (ctx, canvas, size) { + ctx.clearRect(0, 0, canvas.width, canvas.height) + + if (!canvas.style) canvas.style = {} + canvas.height = size + canvas.width = size + canvas.style.height = size + 'px' + canvas.style.width = size + 'px' +} + +function getCanvasElement () { + try { + return document.createElement('canvas') + } catch (e) { + throw new Error('You need to specify a canvas element') + } +} + +exports.render = function render (qrData, canvas, options) { + let opts = options + let canvasEl = canvas + + if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) { + opts = canvas + canvas = undefined + } + + if (!canvas) { + canvasEl = getCanvasElement() + } + + opts = Utils.getOptions(opts) + const size = Utils.getImageWidth(qrData.modules.size, opts) + + const ctx = canvasEl.getContext('2d') + const image = ctx.createImageData(size, size) + Utils.qrToImageData(image.data, qrData, opts) + + clearCanvas(ctx, canvasEl, size) + ctx.putImageData(image, 0, 0) + + return canvasEl +} + +exports.renderToDataURL = function renderToDataURL (qrData, canvas, options) { + let opts = options + + if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) { + opts = canvas + canvas = undefined + } + + if (!opts) opts = {} + + const canvasEl = exports.render(qrData, canvas, opts) + + const type = opts.type || 'image/png' + const rendererOpts = opts.rendererOpts || {} + + return canvasEl.toDataURL(type, rendererOpts.quality) +} diff --git a/node_modules/qrcode/lib/renderer/png.js b/node_modules/qrcode/lib/renderer/png.js new file mode 100644 index 0000000..2742160 --- /dev/null +++ b/node_modules/qrcode/lib/renderer/png.js @@ -0,0 +1,78 @@ +const fs = require('fs') +const PNG = require('pngjs').PNG +const Utils = require('./utils') + +exports.render = function render (qrData, options) { + const opts = Utils.getOptions(options) + const pngOpts = opts.rendererOpts + const size = Utils.getImageWidth(qrData.modules.size, opts) + + pngOpts.width = size + pngOpts.height = size + + const pngImage = new PNG(pngOpts) + Utils.qrToImageData(pngImage.data, qrData, opts) + + return pngImage +} + +exports.renderToDataURL = function renderToDataURL (qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + exports.renderToBuffer(qrData, options, function (err, output) { + if (err) cb(err) + let url = 'data:image/png;base64,' + url += output.toString('base64') + cb(null, url) + }) +} + +exports.renderToBuffer = function renderToBuffer (qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + const png = exports.render(qrData, options) + const buffer = [] + + png.on('error', cb) + + png.on('data', function (data) { + buffer.push(data) + }) + + png.on('end', function () { + cb(null, Buffer.concat(buffer)) + }) + + png.pack() +} + +exports.renderToFile = function renderToFile (path, qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + let called = false + const done = (...args) => { + if (called) return + called = true + cb.apply(null, args) + } + const stream = fs.createWriteStream(path) + + stream.on('error', done) + stream.on('close', done) + + exports.renderToFileStream(stream, qrData, options) +} + +exports.renderToFileStream = function renderToFileStream (stream, qrData, options) { + const png = exports.render(qrData, options) + png.pack().pipe(stream) +} diff --git a/node_modules/qrcode/lib/renderer/svg-tag.js b/node_modules/qrcode/lib/renderer/svg-tag.js new file mode 100644 index 0000000..d0839fe --- /dev/null +++ b/node_modules/qrcode/lib/renderer/svg-tag.js @@ -0,0 +1,81 @@ +const Utils = require('./utils') + +function getColorAttrib (color, attrib) { + const alpha = color.a / 255 + const str = attrib + '="' + color.hex + '"' + + return alpha < 1 + ? str + ' ' + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"' + : str +} + +function svgCmd (cmd, x, y) { + let str = cmd + x + if (typeof y !== 'undefined') str += ' ' + y + + return str +} + +function qrToPath (data, size, margin) { + let path = '' + let moveBy = 0 + let newRow = false + let lineLength = 0 + + for (let i = 0; i < data.length; i++) { + const col = Math.floor(i % size) + const row = Math.floor(i / size) + + if (!col && !newRow) newRow = true + + if (data[i]) { + lineLength++ + + if (!(i > 0 && col > 0 && data[i - 1])) { + path += newRow + ? svgCmd('M', col + margin, 0.5 + row + margin) + : svgCmd('m', moveBy, 0) + + moveBy = 0 + newRow = false + } + + if (!(col + 1 < size && data[i + 1])) { + path += svgCmd('h', lineLength) + lineLength = 0 + } + } else { + moveBy++ + } + } + + return path +} + +exports.render = function render (qrData, options, cb) { + const opts = Utils.getOptions(options) + const size = qrData.modules.size + const data = qrData.modules.data + const qrcodesize = size + opts.margin * 2 + + const bg = !opts.color.light.a + ? '' + : '' + + const path = + '' + + const viewBox = 'viewBox="' + '0 0 ' + qrcodesize + ' ' + qrcodesize + '"' + + const width = !opts.width ? '' : 'width="' + opts.width + '" height="' + opts.width + '" ' + + const svgTag = '' + bg + path + '\n' + + if (typeof cb === 'function') { + cb(null, svgTag) + } + + return svgTag +} diff --git a/node_modules/qrcode/lib/renderer/svg.js b/node_modules/qrcode/lib/renderer/svg.js new file mode 100644 index 0000000..ba99d14 --- /dev/null +++ b/node_modules/qrcode/lib/renderer/svg.js @@ -0,0 +1,19 @@ +const svgTagRenderer = require('./svg-tag') + +exports.render = svgTagRenderer.render + +exports.renderToFile = function renderToFile (path, qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + const fs = require('fs') + const svgTag = exports.render(qrData, options) + + const xmlStr = '' + + '' + + svgTag + + fs.writeFile(path, xmlStr, cb) +} diff --git a/node_modules/qrcode/lib/renderer/terminal.js b/node_modules/qrcode/lib/renderer/terminal.js new file mode 100644 index 0000000..36ddfde --- /dev/null +++ b/node_modules/qrcode/lib/renderer/terminal.js @@ -0,0 +1,9 @@ +const big = require('./terminal/terminal') +const small = require('./terminal/terminal-small') + +exports.render = function (qrData, options, cb) { + if (options && options.small) { + return small.render(qrData, options, cb) + } + return big.render(qrData, options, cb) +} diff --git a/node_modules/qrcode/lib/renderer/terminal/terminal-small.js b/node_modules/qrcode/lib/renderer/terminal/terminal-small.js new file mode 100644 index 0000000..9810d4e --- /dev/null +++ b/node_modules/qrcode/lib/renderer/terminal/terminal-small.js @@ -0,0 +1,85 @@ +const backgroundWhite = '\x1b[47m' +const backgroundBlack = '\x1b[40m' +const foregroundWhite = '\x1b[37m' +const foregroundBlack = '\x1b[30m' +const reset = '\x1b[0m' +const lineSetupNormal = backgroundWhite + foregroundBlack // setup colors +const lineSetupInverse = backgroundBlack + foregroundWhite // setup colors + +const createPalette = function (lineSetup, foregroundWhite, foregroundBlack) { + return { + // 1 ... white, 2 ... black, 0 ... transparent (default) + + '00': reset + ' ' + lineSetup, + '01': reset + foregroundWhite + '▄' + lineSetup, + '02': reset + foregroundBlack + '▄' + lineSetup, + 10: reset + foregroundWhite + '▀' + lineSetup, + 11: ' ', + 12: '▄', + 20: reset + foregroundBlack + '▀' + lineSetup, + 21: '▀', + 22: '█' + } +} + +/** + * Returns code for QR pixel + * @param {boolean[][]} modules + * @param {number} size + * @param {number} x + * @param {number} y + * @return {'0' | '1' | '2'} + */ +const mkCodePixel = function (modules, size, x, y) { + const sizePlus = size + 1 + if ((x >= sizePlus) || (y >= sizePlus) || (y < -1) || (x < -1)) return '0' + if ((x >= size) || (y >= size) || (y < 0) || (x < 0)) return '1' + const idx = (y * size) + x + return modules[idx] ? '2' : '1' +} + +/** + * Returns code for four QR pixels. Suitable as key in palette. + * @param {boolean[][]} modules + * @param {number} size + * @param {number} x + * @param {number} y + * @return {keyof palette} + */ +const mkCode = function (modules, size, x, y) { + return ( + mkCodePixel(modules, size, x, y) + + mkCodePixel(modules, size, x, y + 1) + ) +} + +exports.render = function (qrData, options, cb) { + const size = qrData.modules.size + const data = qrData.modules.data + + const inverse = !!(options && options.inverse) + const lineSetup = options && options.inverse ? lineSetupInverse : lineSetupNormal + const white = inverse ? foregroundBlack : foregroundWhite + const black = inverse ? foregroundWhite : foregroundBlack + + const palette = createPalette(lineSetup, white, black) + const newLine = reset + '\n' + lineSetup + + let output = lineSetup // setup colors + + for (let y = -1; y < size + 1; y += 2) { + for (let x = -1; x < size; x++) { + output += palette[mkCode(data, size, x, y)] + } + + output += palette[mkCode(data, size, size, y)] + newLine + } + + output += reset + + if (typeof cb === 'function') { + cb(null, output) + } + + return output +} diff --git a/node_modules/qrcode/lib/renderer/terminal/terminal.js b/node_modules/qrcode/lib/renderer/terminal/terminal.js new file mode 100644 index 0000000..f15610b --- /dev/null +++ b/node_modules/qrcode/lib/renderer/terminal/terminal.js @@ -0,0 +1,49 @@ +// let Utils = require('./utils') + +exports.render = function (qrData, options, cb) { + const size = qrData.modules.size + const data = qrData.modules.data + + // let opts = Utils.getOptions(options) + + // use same scheme as https://github.com/gtanner/qrcode-terminal because it actually works! =) + const black = '\x1b[40m \x1b[0m' + const white = '\x1b[47m \x1b[0m' + + let output = '' + const hMargin = Array(size + 3).join(white) + const vMargin = Array(2).join(white) + + output += hMargin + '\n' + for (let i = 0; i < size; ++i) { + output += white + for (let j = 0; j < size; j++) { + // let topModule = data[i * size + j] + // let bottomModule = data[(i + 1) * size + j] + + output += data[i * size + j] ? black : white// getBlockChar(topModule, bottomModule) + } + // output += white+'\n' + output += vMargin + '\n' + } + + output += hMargin + '\n' + + if (typeof cb === 'function') { + cb(null, output) + } + + return output +} +/* +exports.renderToFile = function renderToFile (path, qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + let fs = require('fs') + let utf8 = exports.render(qrData, options) + fs.writeFile(path, utf8, cb) +} +*/ diff --git a/node_modules/qrcode/lib/renderer/utf8.js b/node_modules/qrcode/lib/renderer/utf8.js new file mode 100644 index 0000000..d76116e --- /dev/null +++ b/node_modules/qrcode/lib/renderer/utf8.js @@ -0,0 +1,71 @@ +const Utils = require('./utils') + +const BLOCK_CHAR = { + WW: ' ', + WB: '▄', + BB: '█', + BW: '▀' +} + +const INVERTED_BLOCK_CHAR = { + BB: ' ', + BW: '▄', + WW: '█', + WB: '▀' +} + +function getBlockChar (top, bottom, blocks) { + if (top && bottom) return blocks.BB + if (top && !bottom) return blocks.BW + if (!top && bottom) return blocks.WB + return blocks.WW +} + +exports.render = function (qrData, options, cb) { + const opts = Utils.getOptions(options) + let blocks = BLOCK_CHAR + if (opts.color.dark.hex === '#ffffff' || opts.color.light.hex === '#000000') { + blocks = INVERTED_BLOCK_CHAR + } + + const size = qrData.modules.size + const data = qrData.modules.data + + let output = '' + let hMargin = Array(size + (opts.margin * 2) + 1).join(blocks.WW) + hMargin = Array((opts.margin / 2) + 1).join(hMargin + '\n') + + const vMargin = Array(opts.margin + 1).join(blocks.WW) + + output += hMargin + for (let i = 0; i < size; i += 2) { + output += vMargin + for (let j = 0; j < size; j++) { + const topModule = data[i * size + j] + const bottomModule = data[(i + 1) * size + j] + + output += getBlockChar(topModule, bottomModule, blocks) + } + + output += vMargin + '\n' + } + + output += hMargin.slice(0, -1) + + if (typeof cb === 'function') { + cb(null, output) + } + + return output +} + +exports.renderToFile = function renderToFile (path, qrData, options, cb) { + if (typeof cb === 'undefined') { + cb = options + options = undefined + } + + const fs = require('fs') + const utf8 = exports.render(qrData, options) + fs.writeFile(path, utf8, cb) +} diff --git a/node_modules/qrcode/lib/renderer/utils.js b/node_modules/qrcode/lib/renderer/utils.js new file mode 100644 index 0000000..87239dc --- /dev/null +++ b/node_modules/qrcode/lib/renderer/utils.js @@ -0,0 +1,99 @@ +function hex2rgba (hex) { + if (typeof hex === 'number') { + hex = hex.toString() + } + + if (typeof hex !== 'string') { + throw new Error('Color should be defined as hex string') + } + + let hexCode = hex.slice().replace('#', '').split('') + if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) { + throw new Error('Invalid hex color: ' + hex) + } + + // Convert from short to long form (fff -> ffffff) + if (hexCode.length === 3 || hexCode.length === 4) { + hexCode = Array.prototype.concat.apply([], hexCode.map(function (c) { + return [c, c] + })) + } + + // Add default alpha value + if (hexCode.length === 6) hexCode.push('F', 'F') + + const hexValue = parseInt(hexCode.join(''), 16) + + return { + r: (hexValue >> 24) & 255, + g: (hexValue >> 16) & 255, + b: (hexValue >> 8) & 255, + a: hexValue & 255, + hex: '#' + hexCode.slice(0, 6).join('') + } +} + +exports.getOptions = function getOptions (options) { + if (!options) options = {} + if (!options.color) options.color = {} + + const margin = typeof options.margin === 'undefined' || + options.margin === null || + options.margin < 0 + ? 4 + : options.margin + + const width = options.width && options.width >= 21 ? options.width : undefined + const scale = options.scale || 4 + + return { + width: width, + scale: width ? 4 : scale, + margin: margin, + color: { + dark: hex2rgba(options.color.dark || '#000000ff'), + light: hex2rgba(options.color.light || '#ffffffff') + }, + type: options.type, + rendererOpts: options.rendererOpts || {} + } +} + +exports.getScale = function getScale (qrSize, opts) { + return opts.width && opts.width >= qrSize + opts.margin * 2 + ? opts.width / (qrSize + opts.margin * 2) + : opts.scale +} + +exports.getImageWidth = function getImageWidth (qrSize, opts) { + const scale = exports.getScale(qrSize, opts) + return Math.floor((qrSize + opts.margin * 2) * scale) +} + +exports.qrToImageData = function qrToImageData (imgData, qr, opts) { + const size = qr.modules.size + const data = qr.modules.data + const scale = exports.getScale(size, opts) + const symbolSize = Math.floor((size + opts.margin * 2) * scale) + const scaledMargin = opts.margin * scale + const palette = [opts.color.light, opts.color.dark] + + for (let i = 0; i < symbolSize; i++) { + for (let j = 0; j < symbolSize; j++) { + let posDst = (i * symbolSize + j) * 4 + let pxColor = opts.color.light + + if (i >= scaledMargin && j >= scaledMargin && + i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) { + const iSrc = Math.floor((i - scaledMargin) / scale) + const jSrc = Math.floor((j - scaledMargin) / scale) + pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0] + } + + imgData[posDst++] = pxColor.r + imgData[posDst++] = pxColor.g + imgData[posDst++] = pxColor.b + imgData[posDst] = pxColor.a + } + } +} diff --git a/node_modules/qrcode/lib/server.js b/node_modules/qrcode/lib/server.js new file mode 100644 index 0000000..619e398 --- /dev/null +++ b/node_modules/qrcode/lib/server.js @@ -0,0 +1,138 @@ +const canPromise = require('./can-promise') +const QRCode = require('./core/qrcode') +const PngRenderer = require('./renderer/png') +const Utf8Renderer = require('./renderer/utf8') +const TerminalRenderer = require('./renderer/terminal') +const SvgRenderer = require('./renderer/svg') + +function checkParams (text, opts, cb) { + if (typeof text === 'undefined') { + throw new Error('String required as first argument') + } + + if (typeof cb === 'undefined') { + cb = opts + opts = {} + } + + if (typeof cb !== 'function') { + if (!canPromise()) { + throw new Error('Callback required as last argument') + } else { + opts = cb || {} + cb = null + } + } + + return { + opts: opts, + cb: cb + } +} + +function getTypeFromFilename (path) { + return path.slice((path.lastIndexOf('.') - 1 >>> 0) + 2).toLowerCase() +} + +function getRendererFromType (type) { + switch (type) { + case 'svg': + return SvgRenderer + + case 'txt': + case 'utf8': + return Utf8Renderer + + case 'png': + case 'image/png': + default: + return PngRenderer + } +} + +function getStringRendererFromType (type) { + switch (type) { + case 'svg': + return SvgRenderer + + case 'terminal': + return TerminalRenderer + + case 'utf8': + default: + return Utf8Renderer + } +} + +function render (renderFunc, text, params) { + if (!params.cb) { + return new Promise(function (resolve, reject) { + try { + const data = QRCode.create(text, params.opts) + return renderFunc(data, params.opts, function (err, data) { + return err ? reject(err) : resolve(data) + }) + } catch (e) { + reject(e) + } + }) + } + + try { + const data = QRCode.create(text, params.opts) + return renderFunc(data, params.opts, params.cb) + } catch (e) { + params.cb(e) + } +} + +exports.create = QRCode.create + +exports.toCanvas = require('./browser').toCanvas + +exports.toString = function toString (text, opts, cb) { + const params = checkParams(text, opts, cb) + const type = params.opts ? params.opts.type : undefined + const renderer = getStringRendererFromType(type) + return render(renderer.render, text, params) +} + +exports.toDataURL = function toDataURL (text, opts, cb) { + const params = checkParams(text, opts, cb) + const renderer = getRendererFromType(params.opts.type) + return render(renderer.renderToDataURL, text, params) +} + +exports.toBuffer = function toBuffer (text, opts, cb) { + const params = checkParams(text, opts, cb) + const renderer = getRendererFromType(params.opts.type) + return render(renderer.renderToBuffer, text, params) +} + +exports.toFile = function toFile (path, text, opts, cb) { + if (typeof path !== 'string' || !(typeof text === 'string' || typeof text === 'object')) { + throw new Error('Invalid argument') + } + + if ((arguments.length < 3) && !canPromise()) { + throw new Error('Too few arguments provided') + } + + const params = checkParams(text, opts, cb) + const type = params.opts.type || getTypeFromFilename(path) + const renderer = getRendererFromType(type) + const renderToFile = renderer.renderToFile.bind(null, path) + + return render(renderToFile, text, params) +} + +exports.toFileStream = function toFileStream (stream, text, opts) { + if (arguments.length < 2) { + throw new Error('Too few arguments provided') + } + + const params = checkParams(text, opts, stream.emit.bind(stream, 'error')) + const renderer = getRendererFromType('png') // Only png support for now + const renderToFileStream = renderer.renderToFileStream.bind(null, stream) + render(renderToFileStream, text, params) +} diff --git a/node_modules/qrcode/license b/node_modules/qrcode/license new file mode 100644 index 0000000..4e2b3b9 --- /dev/null +++ b/node_modules/qrcode/license @@ -0,0 +1,10 @@ +The MIT License (MIT) + +Copyright (c) 2012 Ryan Day + +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/qrcode/package.json b/node_modules/qrcode/package.json new file mode 100644 index 0000000..6c9ab00 --- /dev/null +++ b/node_modules/qrcode/package.json @@ -0,0 +1,77 @@ +{ + "name": "qrcode", + "description": "QRCode / 2d Barcode api with both server side and client side support using canvas", + "version": "1.5.4", + "author": "Ryan Day ", + "contributors": [ + "Vincenzo Greco ", + "Linus Unnebäck " + ], + "keywords": [ + "qr", + "code", + "canvas", + "qrcode" + ], + "main": "./lib/index.js", + "browser": { + "./lib/index.js": "./lib/browser.js", + "fs": false + }, + "files": [ + "bin", + "build", + "lib", + "helper" + ], + "homepage": "http://github.com/soldair/node-qrcode", + "license": "MIT", + "scripts": { + "lint": "standard", + "pretest": "npm run lint", + "test": "node --throw-deprecation test.js", + "build": "rollup -c", + "prepublish": "npm run build", + "browser": "node examples/clientsideserver.js" + }, + "bin": { + "qrcode": "./bin/qrcode" + }, + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/preset-env": "^7.9.5", + "@rollup/plugin-commonjs": "^11.1.0", + "@rollup/plugin-node-resolve": "^7.1.3", + "browserify": "^16.5.1", + "canvas": "^2.8.0", + "canvasutil": "0.0.4", + "colors": "^1.4.0", + "express": "^4.17.1", + "htmlparser2": "^4.1.0", + "rollup": "^2.6.1", + "rollup-plugin-babel": "^4.4.0", + "rollup-plugin-terser": "^5.3.0", + "sinon": "^9.0.2", + "standard": "^16.0.4", + "tap": "^16.2.0" + }, + "repository": { + "type": "git", + "url": "git://github.com/soldair/node-qrcode.git" + }, + "engines": { + "node": ">=10.13.0" + }, + "standard": { + "ignore": [ + "build/", + "examples/vendors/", + "lib/core/regex.js" + ] + } +} diff --git a/node_modules/require-directory/.jshintrc b/node_modules/require-directory/.jshintrc new file mode 100644 index 0000000..e14e4dc --- /dev/null +++ b/node_modules/require-directory/.jshintrc @@ -0,0 +1,67 @@ +{ + "maxerr" : 50, + "bitwise" : true, + "camelcase" : true, + "curly" : true, + "eqeqeq" : true, + "forin" : true, + "immed" : true, + "indent" : 2, + "latedef" : true, + "newcap" : true, + "noarg" : true, + "noempty" : true, + "nonew" : true, + "plusplus" : true, + "quotmark" : true, + "undef" : true, + "unused" : true, + "strict" : true, + "trailing" : true, + "maxparams" : false, + "maxdepth" : false, + "maxstatements" : false, + "maxcomplexity" : false, + "maxlen" : false, + "asi" : false, + "boss" : false, + "debug" : false, + "eqnull" : true, + "es5" : false, + "esnext" : false, + "moz" : false, + "evil" : false, + "expr" : true, + "funcscope" : true, + "globalstrict" : true, + "iterator" : true, + "lastsemic" : false, + "laxbreak" : false, + "laxcomma" : false, + "loopfunc" : false, + "multistr" : false, + "proto" : false, + "scripturl" : false, + "smarttabs" : false, + "shadow" : false, + "sub" : false, + "supernew" : false, + "validthis" : false, + "browser" : true, + "couch" : false, + "devel" : true, + "dojo" : false, + "jquery" : false, + "mootools" : false, + "node" : true, + "nonstandard" : false, + "prototypejs" : false, + "rhino" : false, + "worker" : false, + "wsh" : false, + "yui" : false, + "nomen" : true, + "onevar" : true, + "passfail" : false, + "white" : true +} diff --git a/node_modules/require-directory/.npmignore b/node_modules/require-directory/.npmignore new file mode 100644 index 0000000..47cf365 --- /dev/null +++ b/node_modules/require-directory/.npmignore @@ -0,0 +1 @@ +test/** diff --git a/node_modules/require-directory/.travis.yml b/node_modules/require-directory/.travis.yml new file mode 100644 index 0000000..20fd86b --- /dev/null +++ b/node_modules/require-directory/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.10 diff --git a/node_modules/require-directory/LICENSE b/node_modules/require-directory/LICENSE new file mode 100644 index 0000000..a70f253 --- /dev/null +++ b/node_modules/require-directory/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2011 Troy Goode + +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/require-directory/README.markdown b/node_modules/require-directory/README.markdown new file mode 100644 index 0000000..926a063 --- /dev/null +++ b/node_modules/require-directory/README.markdown @@ -0,0 +1,184 @@ +# require-directory + +Recursively iterates over specified directory, `require()`'ing each file, and returning a nested hash structure containing those modules. + +**[Follow me (@troygoode) on Twitter!](https://twitter.com/intent/user?screen_name=troygoode)** + +[![NPM](https://nodei.co/npm/require-directory.png?downloads=true&stars=true)](https://nodei.co/npm/require-directory/) + +[![build status](https://secure.travis-ci.org/troygoode/node-require-directory.png)](http://travis-ci.org/troygoode/node-require-directory) + +## How To Use + +### Installation (via [npm](https://npmjs.org/package/require-directory)) + +```bash +$ npm install require-directory +``` + +### Usage + +A common pattern in node.js is to include an index file which creates a hash of the files in its current directory. Given a directory structure like so: + +* app.js +* routes/ + * index.js + * home.js + * auth/ + * login.js + * logout.js + * register.js + +`routes/index.js` uses `require-directory` to build the hash (rather than doing so manually) like so: + +```javascript +var requireDirectory = require('require-directory'); +module.exports = requireDirectory(module); +``` + +`app.js` references `routes/index.js` like any other module, but it now has a hash/tree of the exports from the `./routes/` directory: + +```javascript +var routes = require('./routes'); + +// snip + +app.get('/', routes.home); +app.get('/register', routes.auth.register); +app.get('/login', routes.auth.login); +app.get('/logout', routes.auth.logout); +``` + +The `routes` variable above is the equivalent of this: + +```javascript +var routes = { + home: require('routes/home.js'), + auth: { + login: require('routes/auth/login.js'), + logout: require('routes/auth/logout.js'), + register: require('routes/auth/register.js') + } +}; +``` + +*Note that `routes.index` will be `undefined` as you would hope.* + +### Specifying Another Directory + +You can specify which directory you want to build a tree of (if it isn't the current directory for whatever reason) by passing it as the second parameter. Not specifying the path (`requireDirectory(module)`) is the equivelant of `requireDirectory(module, __dirname)`: + +```javascript +var requireDirectory = require('require-directory'); +module.exports = requireDirectory(module, './some/subdirectory'); +``` + +For example, in the [example in the Usage section](#usage) we could have avoided creating `routes/index.js` and instead changed the first lines of `app.js` to: + +```javascript +var requireDirectory = require('require-directory'); +var routes = requireDirectory(module, './routes'); +``` + +## Options + +You can pass an options hash to `require-directory` as the 2nd parameter (or 3rd if you're passing the path to another directory as the 2nd parameter already). Here are the available options: + +### Whitelisting + +Whitelisting (either via RegExp or function) allows you to specify that only certain files be loaded. + +```javascript +var requireDirectory = require('require-directory'), + whitelist = /onlyinclude.js$/, + hash = requireDirectory(module, {include: whitelist}); +``` + +```javascript +var requireDirectory = require('require-directory'), + check = function(path){ + if(/onlyinclude.js$/.test(path)){ + return true; // don't include + }else{ + return false; // go ahead and include + } + }, + hash = requireDirectory(module, {include: check}); +``` + +### Blacklisting + +Blacklisting (either via RegExp or function) allows you to specify that all but certain files should be loaded. + +```javascript +var requireDirectory = require('require-directory'), + blacklist = /dontinclude\.js$/, + hash = requireDirectory(module, {exclude: blacklist}); +``` + +```javascript +var requireDirectory = require('require-directory'), + check = function(path){ + if(/dontinclude\.js$/.test(path)){ + return false; // don't include + }else{ + return true; // go ahead and include + } + }, + hash = requireDirectory(module, {exclude: check}); +``` + +### Visiting Objects As They're Loaded + +`require-directory` takes a function as the `visit` option that will be called for each module that is added to module.exports. + +```javascript +var requireDirectory = require('require-directory'), + visitor = function(obj) { + console.log(obj); // will be called for every module that is loaded + }, + hash = requireDirectory(module, {visit: visitor}); +``` + +The visitor can also transform the objects by returning a value: + +```javascript +var requireDirectory = require('require-directory'), + visitor = function(obj) { + return obj(new Date()); + }, + hash = requireDirectory(module, {visit: visitor}); +``` + +### Renaming Keys + +```javascript +var requireDirectory = require('require-directory'), + renamer = function(name) { + return name.toUpperCase(); + }, + hash = requireDirectory(module, {rename: renamer}); +``` + +### No Recursion + +```javascript +var requireDirectory = require('require-directory'), + hash = requireDirectory(module, {recurse: false}); +``` + +## Run Unit Tests + +```bash +$ npm run lint +$ npm test +``` + +## License + +[MIT License](http://www.opensource.org/licenses/mit-license.php) + +## Author + +[Troy Goode](https://github.com/TroyGoode) ([troygoode@gmail.com](mailto:troygoode@gmail.com)) + diff --git a/node_modules/require-directory/index.js b/node_modules/require-directory/index.js new file mode 100644 index 0000000..cd37da7 --- /dev/null +++ b/node_modules/require-directory/index.js @@ -0,0 +1,86 @@ +'use strict'; + +var fs = require('fs'), + join = require('path').join, + resolve = require('path').resolve, + dirname = require('path').dirname, + defaultOptions = { + extensions: ['js', 'json', 'coffee'], + recurse: true, + rename: function (name) { + return name; + }, + visit: function (obj) { + return obj; + } + }; + +function checkFileInclusion(path, filename, options) { + return ( + // verify file has valid extension + (new RegExp('\\.(' + options.extensions.join('|') + ')$', 'i').test(filename)) && + + // if options.include is a RegExp, evaluate it and make sure the path passes + !(options.include && options.include instanceof RegExp && !options.include.test(path)) && + + // if options.include is a function, evaluate it and make sure the path passes + !(options.include && typeof options.include === 'function' && !options.include(path, filename)) && + + // if options.exclude is a RegExp, evaluate it and make sure the path doesn't pass + !(options.exclude && options.exclude instanceof RegExp && options.exclude.test(path)) && + + // if options.exclude is a function, evaluate it and make sure the path doesn't pass + !(options.exclude && typeof options.exclude === 'function' && options.exclude(path, filename)) + ); +} + +function requireDirectory(m, path, options) { + var retval = {}; + + // path is optional + if (path && !options && typeof path !== 'string') { + options = path; + path = null; + } + + // default options + options = options || {}; + for (var prop in defaultOptions) { + if (typeof options[prop] === 'undefined') { + options[prop] = defaultOptions[prop]; + } + } + + // if no path was passed in, assume the equivelant of __dirname from caller + // otherwise, resolve path relative to the equivalent of __dirname + path = !path ? dirname(m.filename) : resolve(dirname(m.filename), path); + + // get the path of each file in specified directory, append to current tree node, recurse + fs.readdirSync(path).forEach(function (filename) { + var joined = join(path, filename), + files, + key, + obj; + + if (fs.statSync(joined).isDirectory() && options.recurse) { + // this node is a directory; recurse + files = requireDirectory(m, joined, options); + // exclude empty directories + if (Object.keys(files).length) { + retval[options.rename(filename, joined, filename)] = files; + } + } else { + if (joined !== m.filename && checkFileInclusion(joined, filename, options)) { + // hash node key shouldn't include file extension + key = filename.substring(0, filename.lastIndexOf('.')); + obj = m.require(joined); + retval[options.rename(key, joined, filename)] = options.visit(obj, joined, filename) || obj; + } + } + }); + + return retval; +} + +module.exports = requireDirectory; +module.exports.defaults = defaultOptions; diff --git a/node_modules/require-directory/package.json b/node_modules/require-directory/package.json new file mode 100644 index 0000000..25ece4b --- /dev/null +++ b/node_modules/require-directory/package.json @@ -0,0 +1,40 @@ +{ + "author": "Troy Goode (http://github.com/troygoode/)", + "name": "require-directory", + "version": "2.1.1", + "description": "Recursively iterates over specified directory, require()'ing each file, and returning a nested hash structure containing those modules.", + "keywords": [ + "require", + "directory", + "library", + "recursive" + ], + "homepage": "https://github.com/troygoode/node-require-directory/", + "main": "index.js", + "repository": { + "type": "git", + "url": "git://github.com/troygoode/node-require-directory.git" + }, + "contributors": [ + { + "name": "Troy Goode", + "email": "troygoode@gmail.com", + "web": "http://github.com/troygoode/" + } + ], + "license": "MIT", + "bugs": { + "url": "http://github.com/troygoode/node-require-directory/issues/" + }, + "engines": { + "node": ">=0.10.0" + }, + "devDependencies": { + "jshint": "^2.6.0", + "mocha": "^2.1.0" + }, + "scripts": { + "test": "mocha", + "lint": "jshint index.js test/test.js" + } +} diff --git a/node_modules/require-main-filename/CHANGELOG.md b/node_modules/require-main-filename/CHANGELOG.md new file mode 100644 index 0000000..717d59e --- /dev/null +++ b/node_modules/require-main-filename/CHANGELOG.md @@ -0,0 +1,26 @@ +# Change Log + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + + +# [2.0.0](https://github.com/yargs/require-main-filename/compare/v1.0.2...v2.0.0) (2019-01-28) + + +### Chores + +* drop support for Node 0.10 ([#11](https://github.com/yargs/require-main-filename/issues/11)) ([87f4e13](https://github.com/yargs/require-main-filename/commit/87f4e13)) + + +### BREAKING CHANGES + +* drop support for Node 0.10/0.12 + + + + +## [1.0.2](https://github.com/yargs/require-main-filename/compare/v1.0.1...v1.0.2) (2017-06-16) + + +### Bug Fixes + +* add files to package.json ([#4](https://github.com/yargs/require-main-filename/issues/4)) ([fa29988](https://github.com/yargs/require-main-filename/commit/fa29988)) diff --git a/node_modules/require-main-filename/LICENSE.txt b/node_modules/require-main-filename/LICENSE.txt new file mode 100644 index 0000000..836440b --- /dev/null +++ b/node_modules/require-main-filename/LICENSE.txt @@ -0,0 +1,14 @@ +Copyright (c) 2016, Contributors + +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/require-main-filename/README.md b/node_modules/require-main-filename/README.md new file mode 100644 index 0000000..820d9f5 --- /dev/null +++ b/node_modules/require-main-filename/README.md @@ -0,0 +1,26 @@ +# require-main-filename + +[![Build Status](https://travis-ci.org/yargs/require-main-filename.png)](https://travis-ci.org/yargs/require-main-filename) +[![Coverage Status](https://coveralls.io/repos/yargs/require-main-filename/badge.svg?branch=master)](https://coveralls.io/r/yargs/require-main-filename?branch=master) +[![NPM version](https://img.shields.io/npm/v/require-main-filename.svg)](https://www.npmjs.com/package/require-main-filename) + +`require.main.filename` is great for figuring out the entry +point for the current application. This can be combined with a module like +[pkg-conf](https://www.npmjs.com/package/pkg-conf) to, _as if by magic_, load +top-level configuration. + +Unfortunately, `require.main.filename` sometimes fails when an application is +executed with an alternative process manager, e.g., [iisnode](https://github.com/tjanczuk/iisnode). + +`require-main-filename` is a shim that addresses this problem. + +## Usage + +```js +var main = require('require-main-filename')() +// use main as an alternative to require.main.filename. +``` + +## License + +ISC diff --git a/node_modules/require-main-filename/index.js b/node_modules/require-main-filename/index.js new file mode 100644 index 0000000..dca7f0c --- /dev/null +++ b/node_modules/require-main-filename/index.js @@ -0,0 +1,18 @@ +module.exports = function (_require) { + _require = _require || require + var main = _require.main + if (main && isIISNode(main)) return handleIISNode(main) + else return main ? main.filename : process.cwd() +} + +function isIISNode (main) { + return /\\iisnode\\/.test(main.filename) +} + +function handleIISNode (main) { + if (!main.children.length) { + return main.filename + } else { + return main.children[0].filename + } +} diff --git a/node_modules/require-main-filename/package.json b/node_modules/require-main-filename/package.json new file mode 100644 index 0000000..a549822 --- /dev/null +++ b/node_modules/require-main-filename/package.json @@ -0,0 +1,35 @@ +{ + "name": "require-main-filename", + "version": "2.0.0", + "description": "shim for require.main.filename() that works in as many environments as possible", + "main": "index.js", + "scripts": { + "pretest": "standard", + "test": "tap --coverage test.js", + "release": "standard-version" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/yargs/require-main-filename.git" + }, + "keywords": [ + "require", + "shim", + "iisnode" + ], + "files": [ + "index.js" + ], + "author": "Ben Coe ", + "license": "ISC", + "bugs": { + "url": "https://github.com/yargs/require-main-filename/issues" + }, + "homepage": "https://github.com/yargs/require-main-filename#readme", + "devDependencies": { + "chai": "^4.0.0", + "standard": "^10.0.3", + "standard-version": "^4.0.0", + "tap": "^11.0.0" + } +} diff --git a/node_modules/set-blocking/CHANGELOG.md b/node_modules/set-blocking/CHANGELOG.md new file mode 100644 index 0000000..03bf591 --- /dev/null +++ b/node_modules/set-blocking/CHANGELOG.md @@ -0,0 +1,26 @@ +# Change Log + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + + +# [2.0.0](https://github.com/yargs/set-blocking/compare/v1.0.0...v2.0.0) (2016-05-17) + + +### Features + +* add an isTTY check ([#3](https://github.com/yargs/set-blocking/issues/3)) ([66ce277](https://github.com/yargs/set-blocking/commit/66ce277)) + + +### BREAKING CHANGES + +* stdio/stderr will not be set to blocking if isTTY === false + + + + +# 1.0.0 (2016-05-14) + + +### Features + +* implemented shim for stream._handle.setBlocking ([6bde0c0](https://github.com/yargs/set-blocking/commit/6bde0c0)) diff --git a/node_modules/set-blocking/LICENSE.txt b/node_modules/set-blocking/LICENSE.txt new file mode 100644 index 0000000..836440b --- /dev/null +++ b/node_modules/set-blocking/LICENSE.txt @@ -0,0 +1,14 @@ +Copyright (c) 2016, Contributors + +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/set-blocking/README.md b/node_modules/set-blocking/README.md new file mode 100644 index 0000000..e93b420 --- /dev/null +++ b/node_modules/set-blocking/README.md @@ -0,0 +1,31 @@ +# set-blocking + +[![Build Status](https://travis-ci.org/yargs/set-blocking.svg)](https://travis-ci.org/yargs/set-blocking) +[![NPM version](https://img.shields.io/npm/v/set-blocking.svg)](https://www.npmjs.com/package/set-blocking) +[![Coverage Status](https://coveralls.io/repos/yargs/set-blocking/badge.svg?branch=)](https://coveralls.io/r/yargs/set-blocking?branch=master) +[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version) + +set blocking `stdio` and `stderr` ensuring that terminal output does not truncate. + +```js +const setBlocking = require('set-blocking') +setBlocking(true) +console.log(someLargeStringToOutput) +``` + +## Historical Context/Word of Warning + +This was created as a shim to address the bug discussed in [node #6456](https://github.com/nodejs/node/issues/6456). This bug crops up on +newer versions of Node.js (`0.12+`), truncating terminal output. + +You should be mindful of the side-effects caused by using `set-blocking`: + +* if your module sets blocking to `true`, it will effect other modules + consuming your library. In [yargs](https://github.com/yargs/yargs/blob/master/yargs.js#L653) we only call + `setBlocking(true)` once we already know we are about to call `process.exit(code)`. +* this patch will not apply to subprocesses spawned with `isTTY = true`, this is + the [default `spawn()` behavior](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options). + +## License + +ISC diff --git a/node_modules/set-blocking/index.js b/node_modules/set-blocking/index.js new file mode 100644 index 0000000..6f78774 --- /dev/null +++ b/node_modules/set-blocking/index.js @@ -0,0 +1,7 @@ +module.exports = function (blocking) { + [process.stdout, process.stderr].forEach(function (stream) { + if (stream._handle && stream.isTTY && typeof stream._handle.setBlocking === 'function') { + stream._handle.setBlocking(blocking) + } + }) +} diff --git a/node_modules/set-blocking/package.json b/node_modules/set-blocking/package.json new file mode 100644 index 0000000..c082db7 --- /dev/null +++ b/node_modules/set-blocking/package.json @@ -0,0 +1,42 @@ +{ + "name": "set-blocking", + "version": "2.0.0", + "description": "set blocking stdio and stderr ensuring that terminal output does not truncate", + "main": "index.js", + "scripts": { + "pretest": "standard", + "test": "nyc mocha ./test/*.js", + "coverage": "nyc report --reporter=text-lcov | coveralls", + "version": "standard-version" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/yargs/set-blocking.git" + }, + "keywords": [ + "flush", + "terminal", + "blocking", + "shim", + "stdio", + "stderr" + ], + "author": "Ben Coe ", + "license": "ISC", + "bugs": { + "url": "https://github.com/yargs/set-blocking/issues" + }, + "homepage": "https://github.com/yargs/set-blocking#readme", + "devDependencies": { + "chai": "^3.5.0", + "coveralls": "^2.11.9", + "mocha": "^2.4.5", + "nyc": "^6.4.4", + "standard": "^7.0.1", + "standard-version": "^2.2.1" + }, + "files": [ + "index.js", + "LICENSE.txt" + ] +} \ No newline at end of file diff --git a/node_modules/string-width/index.d.ts b/node_modules/string-width/index.d.ts new file mode 100644 index 0000000..12b5309 --- /dev/null +++ b/node_modules/string-width/index.d.ts @@ -0,0 +1,29 @@ +declare const stringWidth: { + /** + Get the visual width of a string - the number of columns required to display it. + + Some Unicode characters are [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) and use double the normal width. [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) are stripped and doesn't affect the width. + + @example + ``` + import stringWidth = require('string-width'); + + stringWidth('a'); + //=> 1 + + stringWidth('古'); + //=> 2 + + stringWidth('\u001B[1m古\u001B[22m'); + //=> 2 + ``` + */ + (string: string): number; + + // TODO: remove this in the next major version, refactor the whole definition to: + // declare function stringWidth(string: string): number; + // export = stringWidth; + default: typeof stringWidth; +} + +export = stringWidth; diff --git a/node_modules/string-width/index.js b/node_modules/string-width/index.js new file mode 100644 index 0000000..f4d261a --- /dev/null +++ b/node_modules/string-width/index.js @@ -0,0 +1,47 @@ +'use strict'; +const stripAnsi = require('strip-ansi'); +const isFullwidthCodePoint = require('is-fullwidth-code-point'); +const emojiRegex = require('emoji-regex'); + +const stringWidth = string => { + if (typeof string !== 'string' || string.length === 0) { + return 0; + } + + string = stripAnsi(string); + + if (string.length === 0) { + return 0; + } + + string = string.replace(emojiRegex(), ' '); + + let width = 0; + + for (let i = 0; i < string.length; i++) { + const code = string.codePointAt(i); + + // Ignore control characters + if (code <= 0x1F || (code >= 0x7F && code <= 0x9F)) { + continue; + } + + // Ignore combining characters + if (code >= 0x300 && code <= 0x36F) { + continue; + } + + // Surrogates + if (code > 0xFFFF) { + i++; + } + + width += isFullwidthCodePoint(code) ? 2 : 1; + } + + return width; +}; + +module.exports = stringWidth; +// TODO: remove this in the next major version +module.exports.default = stringWidth; diff --git a/node_modules/string-width/license b/node_modules/string-width/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/node_modules/string-width/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/string-width/package.json b/node_modules/string-width/package.json new file mode 100644 index 0000000..28ba7b4 --- /dev/null +++ b/node_modules/string-width/package.json @@ -0,0 +1,56 @@ +{ + "name": "string-width", + "version": "4.2.3", + "description": "Get the visual width of a string - the number of columns required to display it", + "license": "MIT", + "repository": "sindresorhus/string-width", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "string", + "character", + "unicode", + "width", + "visual", + "column", + "columns", + "fullwidth", + "full-width", + "full", + "ansi", + "escape", + "codes", + "cli", + "command-line", + "terminal", + "console", + "cjk", + "chinese", + "japanese", + "korean", + "fixed-width" + ], + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "devDependencies": { + "ava": "^1.4.1", + "tsd": "^0.7.1", + "xo": "^0.24.0" + } +} diff --git a/node_modules/string-width/readme.md b/node_modules/string-width/readme.md new file mode 100644 index 0000000..bdd3141 --- /dev/null +++ b/node_modules/string-width/readme.md @@ -0,0 +1,50 @@ +# string-width + +> Get the visual width of a string - the number of columns required to display it + +Some Unicode characters are [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) and use double the normal width. [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) are stripped and doesn't affect the width. + +Useful to be able to measure the actual width of command-line output. + + +## Install + +``` +$ npm install string-width +``` + + +## Usage + +```js +const stringWidth = require('string-width'); + +stringWidth('a'); +//=> 1 + +stringWidth('古'); +//=> 2 + +stringWidth('\u001B[1m古\u001B[22m'); +//=> 2 +``` + + +## Related + +- [string-width-cli](https://github.com/sindresorhus/string-width-cli) - CLI for this module +- [string-length](https://github.com/sindresorhus/string-length) - Get the real length of a string +- [widest-line](https://github.com/sindresorhus/widest-line) - Get the visual width of the widest line in a string + + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/strip-ansi/index.d.ts b/node_modules/strip-ansi/index.d.ts new file mode 100644 index 0000000..907fccc --- /dev/null +++ b/node_modules/strip-ansi/index.d.ts @@ -0,0 +1,17 @@ +/** +Strip [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) from a string. + +@example +``` +import stripAnsi = require('strip-ansi'); + +stripAnsi('\u001B[4mUnicorn\u001B[0m'); +//=> 'Unicorn' + +stripAnsi('\u001B]8;;https://github.com\u0007Click\u001B]8;;\u0007'); +//=> 'Click' +``` +*/ +declare function stripAnsi(string: string): string; + +export = stripAnsi; diff --git a/node_modules/strip-ansi/index.js b/node_modules/strip-ansi/index.js new file mode 100644 index 0000000..9a593df --- /dev/null +++ b/node_modules/strip-ansi/index.js @@ -0,0 +1,4 @@ +'use strict'; +const ansiRegex = require('ansi-regex'); + +module.exports = string => typeof string === 'string' ? string.replace(ansiRegex(), '') : string; diff --git a/node_modules/strip-ansi/license b/node_modules/strip-ansi/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/node_modules/strip-ansi/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/strip-ansi/package.json b/node_modules/strip-ansi/package.json new file mode 100644 index 0000000..1a41108 --- /dev/null +++ b/node_modules/strip-ansi/package.json @@ -0,0 +1,54 @@ +{ + "name": "strip-ansi", + "version": "6.0.1", + "description": "Strip ANSI escape codes from a string", + "license": "MIT", + "repository": "chalk/strip-ansi", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "strip", + "trim", + "remove", + "ansi", + "styles", + "color", + "colour", + "colors", + "terminal", + "console", + "string", + "tty", + "escape", + "formatting", + "rgb", + "256", + "shell", + "xterm", + "log", + "logging", + "command-line", + "text" + ], + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "devDependencies": { + "ava": "^2.4.0", + "tsd": "^0.10.0", + "xo": "^0.25.3" + } +} diff --git a/node_modules/strip-ansi/readme.md b/node_modules/strip-ansi/readme.md new file mode 100644 index 0000000..7c4b56d --- /dev/null +++ b/node_modules/strip-ansi/readme.md @@ -0,0 +1,46 @@ +# strip-ansi [![Build Status](https://travis-ci.org/chalk/strip-ansi.svg?branch=master)](https://travis-ci.org/chalk/strip-ansi) + +> Strip [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) from a string + + +## Install + +``` +$ npm install strip-ansi +``` + + +## Usage + +```js +const stripAnsi = require('strip-ansi'); + +stripAnsi('\u001B[4mUnicorn\u001B[0m'); +//=> 'Unicorn' + +stripAnsi('\u001B]8;;https://github.com\u0007Click\u001B]8;;\u0007'); +//=> 'Click' +``` + + +## strip-ansi for enterprise + +Available as part of the Tidelift Subscription. + +The maintainers of strip-ansi and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-strip-ansi?utm_source=npm-strip-ansi&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) + + +## Related + +- [strip-ansi-cli](https://github.com/chalk/strip-ansi-cli) - CLI for this module +- [strip-ansi-stream](https://github.com/chalk/strip-ansi-stream) - Streaming version of this module +- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes +- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes +- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right + + +## Maintainers + +- [Sindre Sorhus](https://github.com/sindresorhus) +- [Josh Junon](https://github.com/qix-) + diff --git a/node_modules/which-module/LICENSE b/node_modules/which-module/LICENSE new file mode 100644 index 0000000..ab601b6 --- /dev/null +++ b/node_modules/which-module/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2016, Contributors + +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/which-module/README.md b/node_modules/which-module/README.md new file mode 100644 index 0000000..008a1ae --- /dev/null +++ b/node_modules/which-module/README.md @@ -0,0 +1,58 @@ +# which-module + +> Find the module object for something that was require()d + +[![Build Status](https://travis-ci.org/nexdrew/which-module.svg?branch=master)](https://travis-ci.org/nexdrew/which-module) +[![Coverage Status](https://coveralls.io/repos/github/nexdrew/which-module/badge.svg?branch=master)](https://coveralls.io/github/nexdrew/which-module?branch=master) +[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version) +[![Greenkeeper badge](https://badges.greenkeeper.io/nexdrew/which-module.svg)](https://greenkeeper.io/) + +Find the `module` object in `require.cache` for something that was `require()`d +or `import`ed - essentially a reverse `require()` lookup. + +Useful for libs that want to e.g. lookup a filename for a module or submodule +that it did not `require()` itself. + +## Install and Usage + +``` +npm install --save which-module +``` + +```js +const whichModule = require('which-module') + +console.log(whichModule(require('something'))) +// Module { +// id: '/path/to/project/node_modules/something/index.js', +// exports: [Function], +// parent: ..., +// filename: '/path/to/project/node_modules/something/index.js', +// loaded: true, +// children: [], +// paths: [ '/path/to/project/node_modules/something/node_modules', +// '/path/to/project/node_modules', +// '/path/to/node_modules', +// '/path/node_modules', +// '/node_modules' ] } +``` + +## API + +### `whichModule(exported)` + +Return the [`module` object](https://nodejs.org/api/modules.html#modules_the_module_object), +if any, that represents the given argument in the `require.cache`. + +`exported` can be anything that was previously `require()`d or `import`ed as a +module, submodule, or dependency - which means `exported` is identical to the +`module.exports` returned by this method. + +If `exported` did not come from the `exports` of a `module` in `require.cache`, +then this method returns `null`. + +## License + +ISC © Contributors + +[opensourceregistry_package_id]: # (458260416784685e5ef3091fee54001785dd4360406aa3000315ff256eef6878) diff --git a/node_modules/which-module/index.js b/node_modules/which-module/index.js new file mode 100644 index 0000000..45559b7 --- /dev/null +++ b/node_modules/which-module/index.js @@ -0,0 +1,9 @@ +'use strict' + +module.exports = function whichModule (exported) { + for (var i = 0, files = Object.keys(require.cache), mod; i < files.length; i++) { + mod = require.cache[files[i]] + if (mod.exports === exported) return mod + } + return null +} diff --git a/node_modules/which-module/package.json b/node_modules/which-module/package.json new file mode 100644 index 0000000..6553575 --- /dev/null +++ b/node_modules/which-module/package.json @@ -0,0 +1,41 @@ +{ + "name": "which-module", + "version": "2.0.1", + "description": "Find the module object for something that was require()d", + "main": "index.js", + "scripts": { + "pretest": "standard", + "test": "nyc ava", + "coverage": "nyc report --reporter=text-lcov | coveralls", + "release": "standard-version" + }, + "files": [ + "index.js" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/nexdrew/which-module.git" + }, + "keywords": [ + "which", + "module", + "exports", + "filename", + "require", + "reverse", + "lookup" + ], + "author": "nexdrew", + "license": "ISC", + "bugs": { + "url": "https://github.com/nexdrew/which-module/issues" + }, + "homepage": "https://github.com/nexdrew/which-module#readme", + "devDependencies": { + "ava": "^2.0.0", + "coveralls": "^3.0.3", + "nyc": "^14.0.0", + "standard": "^14.0.0", + "standard-version": "^7.0.0" + } +} diff --git a/node_modules/wrap-ansi/index.js b/node_modules/wrap-ansi/index.js new file mode 100644 index 0000000..a6e5443 --- /dev/null +++ b/node_modules/wrap-ansi/index.js @@ -0,0 +1,186 @@ +'use strict'; +const stringWidth = require('string-width'); +const stripAnsi = require('strip-ansi'); +const ansiStyles = require('ansi-styles'); + +const ESCAPES = new Set([ + '\u001B', + '\u009B' +]); + +const END_CODE = 39; + +const wrapAnsi = code => `${ESCAPES.values().next().value}[${code}m`; + +// Calculate the length of words split on ' ', ignoring +// the extra characters added by ansi escape codes +const wordLengths = string => string.split(' ').map(character => stringWidth(character)); + +// Wrap a long word across multiple rows +// Ansi escape codes do not count towards length +const wrapWord = (rows, word, columns) => { + const characters = [...word]; + + let isInsideEscape = false; + let visible = stringWidth(stripAnsi(rows[rows.length - 1])); + + for (const [index, character] of characters.entries()) { + const characterLength = stringWidth(character); + + if (visible + characterLength <= columns) { + rows[rows.length - 1] += character; + } else { + rows.push(character); + visible = 0; + } + + if (ESCAPES.has(character)) { + isInsideEscape = true; + } else if (isInsideEscape && character === 'm') { + isInsideEscape = false; + continue; + } + + if (isInsideEscape) { + continue; + } + + visible += characterLength; + + if (visible === columns && index < characters.length - 1) { + rows.push(''); + visible = 0; + } + } + + // It's possible that the last row we copy over is only + // ansi escape characters, handle this edge-case + if (!visible && rows[rows.length - 1].length > 0 && rows.length > 1) { + rows[rows.length - 2] += rows.pop(); + } +}; + +// Trims spaces from a string ignoring invisible sequences +const stringVisibleTrimSpacesRight = str => { + const words = str.split(' '); + let last = words.length; + + while (last > 0) { + if (stringWidth(words[last - 1]) > 0) { + break; + } + + last--; + } + + if (last === words.length) { + return str; + } + + return words.slice(0, last).join(' ') + words.slice(last).join(''); +}; + +// The wrap-ansi module can be invoked in either 'hard' or 'soft' wrap mode +// +// 'hard' will never allow a string to take up more than columns characters +// +// 'soft' allows long words to expand past the column length +const exec = (string, columns, options = {}) => { + if (options.trim !== false && string.trim() === '') { + return ''; + } + + let pre = ''; + let ret = ''; + let escapeCode; + + const lengths = wordLengths(string); + let rows = ['']; + + for (const [index, word] of string.split(' ').entries()) { + if (options.trim !== false) { + rows[rows.length - 1] = rows[rows.length - 1].trimLeft(); + } + + let rowLength = stringWidth(rows[rows.length - 1]); + + if (index !== 0) { + if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) { + // If we start with a new word but the current row length equals the length of the columns, add a new row + rows.push(''); + rowLength = 0; + } + + if (rowLength > 0 || options.trim === false) { + rows[rows.length - 1] += ' '; + rowLength++; + } + } + + // In 'hard' wrap mode, the length of a line is never allowed to extend past 'columns' + if (options.hard && lengths[index] > columns) { + const remainingColumns = (columns - rowLength); + const breaksStartingThisLine = 1 + Math.floor((lengths[index] - remainingColumns - 1) / columns); + const breaksStartingNextLine = Math.floor((lengths[index] - 1) / columns); + if (breaksStartingNextLine < breaksStartingThisLine) { + rows.push(''); + } + + wrapWord(rows, word, columns); + continue; + } + + if (rowLength + lengths[index] > columns && rowLength > 0 && lengths[index] > 0) { + if (options.wordWrap === false && rowLength < columns) { + wrapWord(rows, word, columns); + continue; + } + + rows.push(''); + } + + if (rowLength + lengths[index] > columns && options.wordWrap === false) { + wrapWord(rows, word, columns); + continue; + } + + rows[rows.length - 1] += word; + } + + if (options.trim !== false) { + rows = rows.map(stringVisibleTrimSpacesRight); + } + + pre = rows.join('\n'); + + for (const [index, character] of [...pre].entries()) { + ret += character; + + if (ESCAPES.has(character)) { + const code = parseFloat(/\d[^m]*/.exec(pre.slice(index, index + 4))); + escapeCode = code === END_CODE ? null : code; + } + + const code = ansiStyles.codes.get(Number(escapeCode)); + + if (escapeCode && code) { + if (pre[index + 1] === '\n') { + ret += wrapAnsi(code); + } else if (character === '\n') { + ret += wrapAnsi(escapeCode); + } + } + } + + return ret; +}; + +// For each newline, invoke the method separately +module.exports = (string, columns, options) => { + return String(string) + .normalize() + .replace(/\r\n/g, '\n') + .split('\n') + .map(line => exec(line, columns, options)) + .join('\n'); +}; diff --git a/node_modules/wrap-ansi/license b/node_modules/wrap-ansi/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/node_modules/wrap-ansi/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/wrap-ansi/package.json b/node_modules/wrap-ansi/package.json new file mode 100644 index 0000000..1d57c9f --- /dev/null +++ b/node_modules/wrap-ansi/package.json @@ -0,0 +1,61 @@ +{ + "name": "wrap-ansi", + "version": "6.2.0", + "description": "Wordwrap a string with ANSI escape codes", + "license": "MIT", + "repository": "chalk/wrap-ansi", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && nyc ava" + }, + "files": [ + "index.js" + ], + "keywords": [ + "wrap", + "break", + "wordwrap", + "wordbreak", + "linewrap", + "ansi", + "styles", + "color", + "colour", + "colors", + "terminal", + "console", + "cli", + "string", + "tty", + "escape", + "formatting", + "rgb", + "256", + "shell", + "xterm", + "log", + "logging", + "command-line", + "text" + ], + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "devDependencies": { + "ava": "^2.1.0", + "chalk": "^2.4.2", + "coveralls": "^3.0.3", + "has-ansi": "^3.0.0", + "nyc": "^14.1.1", + "xo": "^0.24.0" + } +} diff --git a/node_modules/wrap-ansi/readme.md b/node_modules/wrap-ansi/readme.md new file mode 100644 index 0000000..d81a4d5 --- /dev/null +++ b/node_modules/wrap-ansi/readme.md @@ -0,0 +1,97 @@ +# wrap-ansi [![Build Status](https://travis-ci.org/chalk/wrap-ansi.svg?branch=master)](https://travis-ci.org/chalk/wrap-ansi) [![Coverage Status](https://coveralls.io/repos/github/chalk/wrap-ansi/badge.svg?branch=master)](https://coveralls.io/github/chalk/wrap-ansi?branch=master) + +> Wordwrap a string with [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) + + +## Install + +``` +$ npm install wrap-ansi +``` + + +## Usage + +```js +const chalk = require('chalk'); +const wrapAnsi = require('wrap-ansi'); + +const input = 'The quick brown ' + chalk.red('fox jumped over ') + + 'the lazy ' + chalk.green('dog and then ran away with the unicorn.'); + +console.log(wrapAnsi(input, 20)); +``` + + + + +## API + +### wrapAnsi(string, columns, options?) + +Wrap words to the specified column width. + +#### string + +Type: `string` + +String with ANSI escape codes. Like one styled by [`chalk`](https://github.com/chalk/chalk). Newline characters will be normalized to `\n`. + +#### columns + +Type: `number` + +Number of columns to wrap the text to. + +#### options + +Type: `object` + +##### hard + +Type: `boolean`
+Default: `false` + +By default the wrap is soft, meaning long words may extend past the column width. Setting this to `true` will make it hard wrap at the column width. + +##### wordWrap + +Type: `boolean`
+Default: `true` + +By default, an attempt is made to split words at spaces, ensuring that they don't extend past the configured columns. If wordWrap is `false`, each column will instead be completely filled splitting words as necessary. + +##### trim + +Type: `boolean`
+Default: `true` + +Whitespace on all lines is removed by default. Set this option to `false` if you don't want to trim. + + +## Related + +- [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes +- [cli-truncate](https://github.com/sindresorhus/cli-truncate) - Truncate a string to a specific width in the terminal +- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right +- [jsesc](https://github.com/mathiasbynens/jsesc) - Generate ASCII-only output from Unicode strings. Useful for creating test fixtures. + + +## Maintainers + +- [Sindre Sorhus](https://github.com/sindresorhus) +- [Josh Junon](https://github.com/qix-) +- [Benjamin Coe](https://github.com/bcoe) + + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/y18n/CHANGELOG.md b/node_modules/y18n/CHANGELOG.md new file mode 100644 index 0000000..b7e86e9 --- /dev/null +++ b/node_modules/y18n/CHANGELOG.md @@ -0,0 +1,35 @@ +# Change Log + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + + +### [4.0.3](https://www.github.com/yargs/y18n/compare/y18n-v4.0.2...y18n-v4.0.3) (2021-04-07) + + +### Bug Fixes + +* **release:** 4.x.x should not enforce Node 10 ([#126](https://www.github.com/yargs/y18n/issues/126)) ([1e21a53](https://www.github.com/yargs/y18n/commit/1e21a536e9135d8403a47be88922157a706b7cde)) + +### 4.0.1 (2020-11-30) + +### Bug Fixes + +* address prototype pollution issue ([#108](https://www.github.com/yargs/y18n/issues/108)) ([a9ac604](https://www.github.com/yargs/y18n/commit/a9ac604abf756dec9687be3843e2c93bfe581f25)) + + +# [4.0.0](https://github.com/yargs/y18n/compare/v3.2.1...v4.0.0) (2017-10-10) + + +### Bug Fixes + +* allow support for falsy values like 0 in tagged literal ([#45](https://github.com/yargs/y18n/issues/45)) ([c926123](https://github.com/yargs/y18n/commit/c926123)) + + +### Features + +* **__:** added tagged template literal support ([#44](https://github.com/yargs/y18n/issues/44)) ([0598daf](https://github.com/yargs/y18n/commit/0598daf)) + + +### BREAKING CHANGES + +* **__:** dropping Node 0.10/Node 0.12 support diff --git a/node_modules/y18n/LICENSE b/node_modules/y18n/LICENSE new file mode 100644 index 0000000..3c157f0 --- /dev/null +++ b/node_modules/y18n/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2015, Contributors + +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/y18n/README.md b/node_modules/y18n/README.md new file mode 100644 index 0000000..826474f --- /dev/null +++ b/node_modules/y18n/README.md @@ -0,0 +1,109 @@ +# y18n + +[![Build Status][travis-image]][travis-url] +[![Coverage Status][coveralls-image]][coveralls-url] +[![NPM version][npm-image]][npm-url] +[![js-standard-style][standard-image]][standard-url] +[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org) + +The bare-bones internationalization library used by yargs. + +Inspired by [i18n](https://www.npmjs.com/package/i18n). + +## Examples + +_simple string translation:_ + +```js +var __ = require('y18n').__ + +console.log(__('my awesome string %s', 'foo')) +``` + +output: + +`my awesome string foo` + +_using tagged template literals_ + +```js +var __ = require('y18n').__ +var str = 'foo' + +console.log(__`my awesome string ${str}`) +``` + +output: + +`my awesome string foo` + +_pluralization support:_ + +```js +var __n = require('y18n').__n + +console.log(__n('one fish %s', '%d fishes %s', 2, 'foo')) +``` + +output: + +`2 fishes foo` + +## JSON Language Files + +The JSON language files should be stored in a `./locales` folder. +File names correspond to locales, e.g., `en.json`, `pirate.json`. + +When strings are observed for the first time they will be +added to the JSON file corresponding to the current locale. + +## Methods + +### require('y18n')(config) + +Create an instance of y18n with the config provided, options include: + +* `directory`: the locale directory, default `./locales`. +* `updateFiles`: should newly observed strings be updated in file, default `true`. +* `locale`: what locale should be used. +* `fallbackToLanguage`: should fallback to a language-only file (e.g. `en.json`) + be allowed if a file matching the locale does not exist (e.g. `en_US.json`), + default `true`. + +### y18n.\_\_(str, arg, arg, arg) + +Print a localized string, `%s` will be replaced with `arg`s. + +This function can also be used as a tag for a template literal. You can use it +like this: __`hello ${'world'}`. This will be equivalent to +`__('hello %s', 'world')`. + +### y18n.\_\_n(singularString, pluralString, count, arg, arg, arg) + +Print a localized string with appropriate pluralization. If `%d` is provided +in the string, the `count` will replace this placeholder. + +### y18n.setLocale(str) + +Set the current locale being used. + +### y18n.getLocale() + +What locale is currently being used? + +### y18n.updateLocale(obj) + +Update the current locale with the key value pairs in `obj`. + +## License + +ISC + +[travis-url]: https://travis-ci.org/yargs/y18n +[travis-image]: https://img.shields.io/travis/yargs/y18n.svg +[coveralls-url]: https://coveralls.io/github/yargs/y18n +[coveralls-image]: https://img.shields.io/coveralls/yargs/y18n.svg +[npm-url]: https://npmjs.org/package/y18n +[npm-image]: https://img.shields.io/npm/v/y18n.svg +[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg +[standard-url]: https://github.com/feross/standard diff --git a/node_modules/y18n/index.js b/node_modules/y18n/index.js new file mode 100644 index 0000000..727362a --- /dev/null +++ b/node_modules/y18n/index.js @@ -0,0 +1,188 @@ +var fs = require('fs') +var path = require('path') +var util = require('util') + +function Y18N (opts) { + // configurable options. + opts = opts || {} + this.directory = opts.directory || './locales' + this.updateFiles = typeof opts.updateFiles === 'boolean' ? opts.updateFiles : true + this.locale = opts.locale || 'en' + this.fallbackToLanguage = typeof opts.fallbackToLanguage === 'boolean' ? opts.fallbackToLanguage : true + + // internal stuff. + this.cache = Object.create(null) + this.writeQueue = [] +} + +Y18N.prototype.__ = function () { + if (typeof arguments[0] !== 'string') { + return this._taggedLiteral.apply(this, arguments) + } + var args = Array.prototype.slice.call(arguments) + var str = args.shift() + var cb = function () {} // start with noop. + + if (typeof args[args.length - 1] === 'function') cb = args.pop() + cb = cb || function () {} // noop. + + if (!this.cache[this.locale]) this._readLocaleFile() + + // we've observed a new string, update the language file. + if (!this.cache[this.locale][str] && this.updateFiles) { + this.cache[this.locale][str] = str + + // include the current directory and locale, + // since these values could change before the + // write is performed. + this._enqueueWrite([this.directory, this.locale, cb]) + } else { + cb() + } + + return util.format.apply(util, [this.cache[this.locale][str] || str].concat(args)) +} + +Y18N.prototype._taggedLiteral = function (parts) { + var args = arguments + var str = '' + parts.forEach(function (part, i) { + var arg = args[i + 1] + str += part + if (typeof arg !== 'undefined') { + str += '%s' + } + }) + return this.__.apply(null, [str].concat([].slice.call(arguments, 1))) +} + +Y18N.prototype._enqueueWrite = function (work) { + this.writeQueue.push(work) + if (this.writeQueue.length === 1) this._processWriteQueue() +} + +Y18N.prototype._processWriteQueue = function () { + var _this = this + var work = this.writeQueue[0] + + // destructure the enqueued work. + var directory = work[0] + var locale = work[1] + var cb = work[2] + + var languageFile = this._resolveLocaleFile(directory, locale) + var serializedLocale = JSON.stringify(this.cache[locale], null, 2) + + fs.writeFile(languageFile, serializedLocale, 'utf-8', function (err) { + _this.writeQueue.shift() + if (_this.writeQueue.length > 0) _this._processWriteQueue() + cb(err) + }) +} + +Y18N.prototype._readLocaleFile = function () { + var localeLookup = {} + var languageFile = this._resolveLocaleFile(this.directory, this.locale) + + try { + localeLookup = JSON.parse(fs.readFileSync(languageFile, 'utf-8')) + } catch (err) { + if (err instanceof SyntaxError) { + err.message = 'syntax error in ' + languageFile + } + + if (err.code === 'ENOENT') localeLookup = {} + else throw err + } + + this.cache[this.locale] = localeLookup +} + +Y18N.prototype._resolveLocaleFile = function (directory, locale) { + var file = path.resolve(directory, './', locale + '.json') + if (this.fallbackToLanguage && !this._fileExistsSync(file) && ~locale.lastIndexOf('_')) { + // attempt fallback to language only + var languageFile = path.resolve(directory, './', locale.split('_')[0] + '.json') + if (this._fileExistsSync(languageFile)) file = languageFile + } + return file +} + +// this only exists because fs.existsSync() "will be deprecated" +// see https://nodejs.org/api/fs.html#fs_fs_existssync_path +Y18N.prototype._fileExistsSync = function (file) { + try { + return fs.statSync(file).isFile() + } catch (err) { + return false + } +} + +Y18N.prototype.__n = function () { + var args = Array.prototype.slice.call(arguments) + var singular = args.shift() + var plural = args.shift() + var quantity = args.shift() + + var cb = function () {} // start with noop. + if (typeof args[args.length - 1] === 'function') cb = args.pop() + + if (!this.cache[this.locale]) this._readLocaleFile() + + var str = quantity === 1 ? singular : plural + if (this.cache[this.locale][singular]) { + str = this.cache[this.locale][singular][quantity === 1 ? 'one' : 'other'] + } + + // we've observed a new string, update the language file. + if (!this.cache[this.locale][singular] && this.updateFiles) { + this.cache[this.locale][singular] = { + one: singular, + other: plural + } + + // include the current directory and locale, + // since these values could change before the + // write is performed. + this._enqueueWrite([this.directory, this.locale, cb]) + } else { + cb() + } + + // if a %d placeholder is provided, add quantity + // to the arguments expanded by util.format. + var values = [str] + if (~str.indexOf('%d')) values.push(quantity) + + return util.format.apply(util, values.concat(args)) +} + +Y18N.prototype.setLocale = function (locale) { + this.locale = locale +} + +Y18N.prototype.getLocale = function () { + return this.locale +} + +Y18N.prototype.updateLocale = function (obj) { + if (!this.cache[this.locale]) this._readLocaleFile() + + for (var key in obj) { + this.cache[this.locale][key] = obj[key] + } +} + +module.exports = function (opts) { + var y18n = new Y18N(opts) + + // bind all functions to y18n, so that + // they can be used in isolation. + for (var key in y18n) { + if (typeof y18n[key] === 'function') { + y18n[key] = y18n[key].bind(y18n) + } + } + + return y18n +} diff --git a/node_modules/y18n/package.json b/node_modules/y18n/package.json new file mode 100644 index 0000000..6f08863 --- /dev/null +++ b/node_modules/y18n/package.json @@ -0,0 +1,39 @@ +{ + "name": "y18n", + "version": "4.0.3", + "description": "the bare-bones internationalization library used by yargs", + "main": "index.js", + "scripts": { + "pretest": "standard", + "test": "nyc mocha", + "coverage": "nyc report --reporter=text-lcov | coveralls", + "release": "standard-version" + }, + "repository": { + "type": "git", + "url": "git@github.com:yargs/y18n.git" + }, + "files": [ + "index.js" + ], + "keywords": [ + "i18n", + "internationalization", + "yargs" + ], + "author": "Ben Coe ", + "license": "ISC", + "bugs": { + "url": "https://github.com/yargs/y18n/issues" + }, + "homepage": "https://github.com/yargs/y18n", + "devDependencies": { + "chai": "^4.0.1", + "coveralls": "^3.0.0", + "mocha": "^4.0.1", + "nyc": "^11.0.1", + "rimraf": "^2.5.0", + "standard": "^10.0.0-beta.0", + "standard-version": "^4.2.0" + } +} diff --git a/node_modules/yargs-parser/CHANGELOG.md b/node_modules/yargs-parser/CHANGELOG.md new file mode 100644 index 0000000..d91dc51 --- /dev/null +++ b/node_modules/yargs-parser/CHANGELOG.md @@ -0,0 +1,601 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +### [18.1.3](https://www.github.com/yargs/yargs-parser/compare/v18.1.2...v18.1.3) (2020-04-16) + + +### Bug Fixes + +* **setArg:** options using camel-case and dot-notation populated twice ([#268](https://www.github.com/yargs/yargs-parser/issues/268)) ([f7e15b9](https://www.github.com/yargs/yargs-parser/commit/f7e15b9800900b9856acac1a830a5f35847be73e)) + +### [18.1.2](https://www.github.com/yargs/yargs-parser/compare/v18.1.1...v18.1.2) (2020-03-26) + + +### Bug Fixes + +* **array, nargs:** support -o=--value and --option=--value format ([#262](https://www.github.com/yargs/yargs-parser/issues/262)) ([41d3f81](https://www.github.com/yargs/yargs-parser/commit/41d3f8139e116706b28de9b0de3433feb08d2f13)) + +### [18.1.1](https://www.github.com/yargs/yargs-parser/compare/v18.1.0...v18.1.1) (2020-03-16) + + +### Bug Fixes + +* \_\_proto\_\_ will now be replaced with \_\_\_proto\_\_\_ in parse ([#258](https://www.github.com/yargs/yargs-parser/issues/258)), patching a potential +prototype pollution vulnerability. This was reported by the Snyk Security Research Team.([63810ca](https://www.github.com/yargs/yargs-parser/commit/63810ca1ae1a24b08293a4d971e70e058c7a41e2)) + +## [18.1.0](https://www.github.com/yargs/yargs-parser/compare/v18.0.0...v18.1.0) (2020-03-07) + + +### Features + +* introduce single-digit boolean aliases ([#255](https://www.github.com/yargs/yargs-parser/issues/255)) ([9c60265](https://www.github.com/yargs/yargs-parser/commit/9c60265fd7a03cb98e6df3e32c8c5e7508d9f56f)) + +## [18.0.0](https://www.github.com/yargs/yargs-parser/compare/v17.1.0...v18.0.0) (2020-03-02) + + +### ⚠ BREAKING CHANGES + +* the narg count is now enforced when parsing arrays. + +### Features + +* NaN can now be provided as a value for nargs, indicating "at least" one value is expected for array ([#251](https://www.github.com/yargs/yargs-parser/issues/251)) ([9db4be8](https://www.github.com/yargs/yargs-parser/commit/9db4be81417a2c7097128db34d86fe70ef4af70c)) + +## [17.1.0](https://www.github.com/yargs/yargs-parser/compare/v17.0.1...v17.1.0) (2020-03-01) + + +### Features + +* introduce greedy-arrays config, for specifying whether arrays consume multiple positionals ([#249](https://www.github.com/yargs/yargs-parser/issues/249)) ([60e880a](https://www.github.com/yargs/yargs-parser/commit/60e880a837046314d89fa4725f923837fd33a9eb)) + +### [17.0.1](https://www.github.com/yargs/yargs-parser/compare/v17.0.0...v17.0.1) (2020-02-29) + + +### Bug Fixes + +* normalized keys were not enumerable ([#247](https://www.github.com/yargs/yargs-parser/issues/247)) ([57119f9](https://www.github.com/yargs/yargs-parser/commit/57119f9f17cf27499bd95e61c2f72d18314f11ba)) + +## [17.0.0](https://www.github.com/yargs/yargs-parser/compare/v16.1.0...v17.0.0) (2020-02-10) + + +### ⚠ BREAKING CHANGES + +* this reverts parsing behavior of booleans to that of yargs@14 +* objects used during parsing are now created with a null +prototype. There may be some scenarios where this change in behavior +leaks externally. + +### Features + +* boolean arguments will not be collected into an implicit array ([#236](https://www.github.com/yargs/yargs-parser/issues/236)) ([34c4e19](https://www.github.com/yargs/yargs-parser/commit/34c4e19bae4e7af63e3cb6fa654a97ed476e5eb5)) +* introduce nargs-eats-options config option ([#246](https://www.github.com/yargs/yargs-parser/issues/246)) ([d50822a](https://www.github.com/yargs/yargs-parser/commit/d50822ac10e1b05f2e9643671ca131ac251b6732)) + + +### Bug Fixes + +* address bugs with "uknown-options-as-args" ([bc023e3](https://www.github.com/yargs/yargs-parser/commit/bc023e3b13e20a118353f9507d1c999bf388a346)) +* array should take precedence over nargs, but enforce nargs ([#243](https://www.github.com/yargs/yargs-parser/issues/243)) ([4cbc188](https://www.github.com/yargs/yargs-parser/commit/4cbc188b7abb2249529a19c090338debdad2fe6c)) +* support keys that collide with object prototypes ([#234](https://www.github.com/yargs/yargs-parser/issues/234)) ([1587b6d](https://www.github.com/yargs/yargs-parser/commit/1587b6d91db853a9109f1be6b209077993fee4de)) +* unknown options terminated with digits now handled by unknown-options-as-args ([#238](https://www.github.com/yargs/yargs-parser/issues/238)) ([d36cdfa](https://www.github.com/yargs/yargs-parser/commit/d36cdfa854254d7c7e0fe1d583818332ac46c2a5)) + +## [16.1.0](https://www.github.com/yargs/yargs-parser/compare/v16.0.0...v16.1.0) (2019-11-01) + + +### ⚠ BREAKING CHANGES + +* populate error if incompatible narg/count or array/count options are used (#191) + +### Features + +* options that have had their default value used are now tracked ([#211](https://www.github.com/yargs/yargs-parser/issues/211)) ([a525234](https://www.github.com/yargs/yargs-parser/commit/a525234558c847deedd73f8792e0a3b77b26e2c0)) +* populate error if incompatible narg/count or array/count options are used ([#191](https://www.github.com/yargs/yargs-parser/issues/191)) ([84a401f](https://www.github.com/yargs/yargs-parser/commit/84a401f0fa3095e0a19661670d1570d0c3b9d3c9)) + + +### Reverts + +* revert 16.0.0 CHANGELOG entry ([920320a](https://www.github.com/yargs/yargs-parser/commit/920320ad9861bbfd58eda39221ae211540fc1daf)) + +## [15.0.0](https://github.com/yargs/yargs-parser/compare/v14.0.0...v15.0.0) (2019-10-07) + + +### Features + +* rework `collect-unknown-options` into `unknown-options-as-args`, providing more comprehensive functionality ([ef771ca](https://github.com/yargs/yargs-parser/commit/ef771ca)) + + +### BREAKING CHANGES + +* rework `collect-unknown-options` into `unknown-options-as-args`, providing more comprehensive functionality + + + +## [14.0.0](https://github.com/yargs/yargs-parser/compare/v13.1.1...v14.0.0) (2019-09-06) + + +### Bug Fixes + +* boolean arrays with default values ([#185](https://github.com/yargs/yargs-parser/issues/185)) ([7d42572](https://github.com/yargs/yargs-parser/commit/7d42572)) +* boolean now behaves the same as other array types ([#184](https://github.com/yargs/yargs-parser/issues/184)) ([17ca3bd](https://github.com/yargs/yargs-parser/commit/17ca3bd)) +* eatNargs() for 'opt.narg === 0' and boolean typed options ([#188](https://github.com/yargs/yargs-parser/issues/188)) ([c5a1db0](https://github.com/yargs/yargs-parser/commit/c5a1db0)) +* maybeCoerceNumber now takes precedence over coerce return value ([#182](https://github.com/yargs/yargs-parser/issues/182)) ([2f26436](https://github.com/yargs/yargs-parser/commit/2f26436)) +* take into account aliases when appending arrays from config object ([#199](https://github.com/yargs/yargs-parser/issues/199)) ([f8a2d3f](https://github.com/yargs/yargs-parser/commit/f8a2d3f)) + + +### Features + +* add configuration option to "collect-unknown-options" ([#181](https://github.com/yargs/yargs-parser/issues/181)) ([7909cc4](https://github.com/yargs/yargs-parser/commit/7909cc4)) +* maybeCoerceNumber() now takes into account arrays ([#187](https://github.com/yargs/yargs-parser/issues/187)) ([31c204b](https://github.com/yargs/yargs-parser/commit/31c204b)) + + +### BREAKING CHANGES + +* unless "parse-numbers" is set to "false", arrays of numeric strings are now parsed as numbers, rather than strings. +* we have dropped the broken "defaulted" functionality; we would like to revisit adding this in the future. +* maybeCoerceNumber now takes precedence over coerce return value (#182) + + + +### [13.1.1](https://www.github.com/yargs/yargs-parser/compare/v13.1.0...v13.1.1) (2019-06-10) + + +### Bug Fixes + +* convert values to strings when tokenizing ([#167](https://www.github.com/yargs/yargs-parser/issues/167)) ([57b7883](https://www.github.com/yargs/yargs-parser/commit/57b7883)) +* nargs should allow duplicates when duplicate-arguments-array=false ([#164](https://www.github.com/yargs/yargs-parser/issues/164)) ([47ccb0b](https://www.github.com/yargs/yargs-parser/commit/47ccb0b)) +* should populate "_" when given config with "short-option-groups" false ([#179](https://www.github.com/yargs/yargs-parser/issues/179)) ([6055974](https://www.github.com/yargs/yargs-parser/commit/6055974)) + +## [13.1.0](https://github.com/yargs/yargs-parser/compare/v13.0.0...v13.1.0) (2019-05-05) + + +### Features + +* add `strip-aliased` and `strip-dashed` configuration options. ([#172](https://github.com/yargs/yargs-parser/issues/172)) ([a3936aa](https://github.com/yargs/yargs-parser/commit/a3936aa)) +* support boolean which do not consume next argument. ([#171](https://github.com/yargs/yargs-parser/issues/171)) ([0ae7fcb](https://github.com/yargs/yargs-parser/commit/0ae7fcb)) + + + + +# [13.0.0](https://github.com/yargs/yargs-parser/compare/v12.0.0...v13.0.0) (2019-02-02) + + +### Features + +* don't coerce number from string with leading '0' or '+' ([#158](https://github.com/yargs/yargs-parser/issues/158)) ([18d0fd5](https://github.com/yargs/yargs-parser/commit/18d0fd5)) + + +### BREAKING CHANGES + +* options with leading '+' or '0' now parse as strings + + + + +# [12.0.0](https://github.com/yargs/yargs-parser/compare/v11.1.1...v12.0.0) (2019-01-29) + + +### Bug Fixes + +* better handling of quoted strings ([#153](https://github.com/yargs/yargs-parser/issues/153)) ([2fb71b2](https://github.com/yargs/yargs-parser/commit/2fb71b2)) + + +### Features + +* default value is now used if no right-hand value provided for numbers/strings ([#156](https://github.com/yargs/yargs-parser/issues/156)) ([5a7c46a](https://github.com/yargs/yargs-parser/commit/5a7c46a)) + + +### BREAKING CHANGES + +* a flag with no right-hand value no longer populates defaulted options with `undefined`. +* quotes at beginning and endings of strings are not removed during parsing. + + + + +## [11.1.1](https://github.com/yargs/yargs-parser/compare/v11.1.0...v11.1.1) (2018-11-19) + + +### Bug Fixes + +* ensure empty string is added into argv._ ([#140](https://github.com/yargs/yargs-parser/issues/140)) ([79cda98](https://github.com/yargs/yargs-parser/commit/79cda98)) + + +### Reverts + +* make requiresArg work in conjunction with arrays ([#136](https://github.com/yargs/yargs-parser/issues/136)) ([f4a3063](https://github.com/yargs/yargs-parser/commit/f4a3063)) + + + + +# [11.1.0](https://github.com/yargs/yargs-parser/compare/v11.0.0...v11.1.0) (2018-11-10) + + +### Bug Fixes + +* handling of one char alias ([#139](https://github.com/yargs/yargs-parser/issues/139)) ([ee56e31](https://github.com/yargs/yargs-parser/commit/ee56e31)) + + +### Features + +* add halt-at-non-option configuration option ([#130](https://github.com/yargs/yargs-parser/issues/130)) ([a849fce](https://github.com/yargs/yargs-parser/commit/a849fce)) + + + + +# [11.0.0](https://github.com/yargs/yargs-parser/compare/v10.1.0...v11.0.0) (2018-10-06) + + +### Bug Fixes + +* flatten-duplicate-arrays:false for more than 2 arrays ([#128](https://github.com/yargs/yargs-parser/issues/128)) ([2bc395f](https://github.com/yargs/yargs-parser/commit/2bc395f)) +* hyphenated flags combined with dot notation broke parsing ([#131](https://github.com/yargs/yargs-parser/issues/131)) ([dc788da](https://github.com/yargs/yargs-parser/commit/dc788da)) +* make requiresArg work in conjunction with arrays ([#136](https://github.com/yargs/yargs-parser/issues/136)) ([77ae1d4](https://github.com/yargs/yargs-parser/commit/77ae1d4)) + + +### Chores + +* update dependencies ([6dc42a1](https://github.com/yargs/yargs-parser/commit/6dc42a1)) + + +### Features + +* also add camelCase array options ([#125](https://github.com/yargs/yargs-parser/issues/125)) ([08c0117](https://github.com/yargs/yargs-parser/commit/08c0117)) +* array.type can now be provided, supporting coercion ([#132](https://github.com/yargs/yargs-parser/issues/132)) ([4b8cfce](https://github.com/yargs/yargs-parser/commit/4b8cfce)) + + +### BREAKING CHANGES + +* drops Node 4 support +* the argv object is now populated differently (correctly) when hyphens and dot notation are used in conjunction. + + + + +# [10.1.0](https://github.com/yargs/yargs-parser/compare/v10.0.0...v10.1.0) (2018-06-29) + + +### Features + +* add `set-placeholder-key` configuration ([#123](https://github.com/yargs/yargs-parser/issues/123)) ([19386ee](https://github.com/yargs/yargs-parser/commit/19386ee)) + + + + +# [10.0.0](https://github.com/yargs/yargs-parser/compare/v9.0.2...v10.0.0) (2018-04-04) + + +### Bug Fixes + +* do not set boolean flags if not defined in `argv` ([#119](https://github.com/yargs/yargs-parser/issues/119)) ([f6e6599](https://github.com/yargs/yargs-parser/commit/f6e6599)) + + +### BREAKING CHANGES + +* `boolean` flags defined without a `default` value will now behave like other option type and won't be set in the parsed results when the user doesn't set the corresponding CLI arg. + +Previous behavior: +```js +var parse = require('yargs-parser'); + +parse('--flag', {boolean: ['flag']}); +// => { _: [], flag: true } + +parse('--no-flag', {boolean: ['flag']}); +// => { _: [], flag: false } + +parse('', {boolean: ['flag']}); +// => { _: [], flag: false } +``` + +New behavior: +```js +var parse = require('yargs-parser'); + +parse('--flag', {boolean: ['flag']}); +// => { _: [], flag: true } + +parse('--no-flag', {boolean: ['flag']}); +// => { _: [], flag: false } + +parse('', {boolean: ['flag']}); +// => { _: [] } => flag not set similarly to other option type +``` + + + + +## [9.0.2](https://github.com/yargs/yargs-parser/compare/v9.0.1...v9.0.2) (2018-01-20) + + +### Bug Fixes + +* nargs was still aggressively consuming too many arguments ([9b28aad](https://github.com/yargs/yargs-parser/commit/9b28aad)) + + + + +## [9.0.1](https://github.com/yargs/yargs-parser/compare/v9.0.0...v9.0.1) (2018-01-20) + + +### Bug Fixes + +* nargs was consuming too many arguments ([4fef206](https://github.com/yargs/yargs-parser/commit/4fef206)) + + + + +# [9.0.0](https://github.com/yargs/yargs-parser/compare/v8.1.0...v9.0.0) (2018-01-20) + + +### Features + +* narg arguments no longer consume flag arguments ([#114](https://github.com/yargs/yargs-parser/issues/114)) ([60bb9b3](https://github.com/yargs/yargs-parser/commit/60bb9b3)) + + +### BREAKING CHANGES + +* arguments of form --foo, -abc, will no longer be consumed by nargs + + + + +# [8.1.0](https://github.com/yargs/yargs-parser/compare/v8.0.0...v8.1.0) (2017-12-20) + + +### Bug Fixes + +* allow null config values ([#108](https://github.com/yargs/yargs-parser/issues/108)) ([d8b14f9](https://github.com/yargs/yargs-parser/commit/d8b14f9)) +* ensure consistent parsing of dot-notation arguments ([#102](https://github.com/yargs/yargs-parser/issues/102)) ([c9bd79c](https://github.com/yargs/yargs-parser/commit/c9bd79c)) +* implement [@antoniom](https://github.com/antoniom)'s fix for camel-case expansion ([3087e1d](https://github.com/yargs/yargs-parser/commit/3087e1d)) +* only run coercion functions once, despite aliases. ([#76](https://github.com/yargs/yargs-parser/issues/76)) ([#103](https://github.com/yargs/yargs-parser/issues/103)) ([507aaef](https://github.com/yargs/yargs-parser/commit/507aaef)) +* scientific notation circumvented bounds check ([#110](https://github.com/yargs/yargs-parser/issues/110)) ([3571f57](https://github.com/yargs/yargs-parser/commit/3571f57)) +* tokenizer should ignore spaces at the beginning of the argString ([#106](https://github.com/yargs/yargs-parser/issues/106)) ([f34ead9](https://github.com/yargs/yargs-parser/commit/f34ead9)) + + +### Features + +* make combining arrays a configurable option ([#111](https://github.com/yargs/yargs-parser/issues/111)) ([c8bf536](https://github.com/yargs/yargs-parser/commit/c8bf536)) +* merge array from arguments with array from config ([#83](https://github.com/yargs/yargs-parser/issues/83)) ([806ddd6](https://github.com/yargs/yargs-parser/commit/806ddd6)) + + + + +# [8.0.0](https://github.com/yargs/yargs-parser/compare/v7.0.0...v8.0.0) (2017-10-05) + + +### Bug Fixes + +* Ignore multiple spaces between arguments. ([#100](https://github.com/yargs/yargs-parser/issues/100)) ([d137227](https://github.com/yargs/yargs-parser/commit/d137227)) + + +### Features + +* allow configuration of prefix for boolean negation ([#94](https://github.com/yargs/yargs-parser/issues/94)) ([00bde7d](https://github.com/yargs/yargs-parser/commit/00bde7d)) +* reworking how numbers are parsed ([#104](https://github.com/yargs/yargs-parser/issues/104)) ([fba00eb](https://github.com/yargs/yargs-parser/commit/fba00eb)) + + +### BREAKING CHANGES + +* strings that fail `Number.isSafeInteger()` are no longer coerced into numbers. + + + + +# [7.0.0](https://github.com/yargs/yargs-parser/compare/v6.0.1...v7.0.0) (2017-05-02) + + +### Chores + +* revert populate-- logic ([#91](https://github.com/yargs/yargs-parser/issues/91)) ([6003e6d](https://github.com/yargs/yargs-parser/commit/6003e6d)) + + +### BREAKING CHANGES + +* populate-- now defaults to false. + + + + +## [6.0.1](https://github.com/yargs/yargs-parser/compare/v6.0.0...v6.0.1) (2017-05-01) + + +### Bug Fixes + +* default '--' to undefined when not provided; this is closer to the array API ([#90](https://github.com/yargs/yargs-parser/issues/90)) ([4e739cc](https://github.com/yargs/yargs-parser/commit/4e739cc)) + + + + +# [6.0.0](https://github.com/yargs/yargs-parser/compare/v4.2.1...v6.0.0) (2017-05-01) + + +### Bug Fixes + +* environment variables should take precedence over config file ([#81](https://github.com/yargs/yargs-parser/issues/81)) ([76cee1f](https://github.com/yargs/yargs-parser/commit/76cee1f)) +* parsing hints should apply for dot notation keys ([#86](https://github.com/yargs/yargs-parser/issues/86)) ([3e47d62](https://github.com/yargs/yargs-parser/commit/3e47d62)) + + +### Chores + +* upgrade to newest version of camelcase ([#87](https://github.com/yargs/yargs-parser/issues/87)) ([f1903aa](https://github.com/yargs/yargs-parser/commit/f1903aa)) + + +### Features + +* add -- option which allows arguments after the -- flag to be returned separated from positional arguments ([#84](https://github.com/yargs/yargs-parser/issues/84)) ([2572ca8](https://github.com/yargs/yargs-parser/commit/2572ca8)) +* when parsing stops, we now populate "--" by default ([#88](https://github.com/yargs/yargs-parser/issues/88)) ([cd666db](https://github.com/yargs/yargs-parser/commit/cd666db)) + + +### BREAKING CHANGES + +* rather than placing arguments in "_", when parsing is stopped via "--"; we now populate an array called "--" by default. +* camelcase now requires Node 4+. +* environment variables will now override config files (args, env, config-file, config-object) + + + + +# [5.0.0](https://github.com/yargs/yargs-parser/compare/v4.2.1...v5.0.0) (2017-02-18) + + +### Bug Fixes + +* environment variables should take precedence over config file ([#81](https://github.com/yargs/yargs-parser/issues/81)) ([76cee1f](https://github.com/yargs/yargs-parser/commit/76cee1f)) + + +### BREAKING CHANGES + +* environment variables will now override config files (args, env, config-file, config-object) + + + + +## [4.2.1](https://github.com/yargs/yargs-parser/compare/v4.2.0...v4.2.1) (2017-01-02) + + +### Bug Fixes + +* flatten/duplicate regression ([#75](https://github.com/yargs/yargs-parser/issues/75)) ([68d68a0](https://github.com/yargs/yargs-parser/commit/68d68a0)) + + + + +# [4.2.0](https://github.com/yargs/yargs-parser/compare/v4.1.0...v4.2.0) (2016-12-01) + + +### Bug Fixes + +* inner objects in configs had their keys appended to top-level key when dot-notation was disabled ([#72](https://github.com/yargs/yargs-parser/issues/72)) ([0b1b5f9](https://github.com/yargs/yargs-parser/commit/0b1b5f9)) + + +### Features + +* allow multiple arrays to be provided, rather than always combining ([#71](https://github.com/yargs/yargs-parser/issues/71)) ([0f0fb2d](https://github.com/yargs/yargs-parser/commit/0f0fb2d)) + + + + +# [4.1.0](https://github.com/yargs/yargs-parser/compare/v4.0.2...v4.1.0) (2016-11-07) + + +### Features + +* apply coercions to default options ([#65](https://github.com/yargs/yargs-parser/issues/65)) ([c79052b](https://github.com/yargs/yargs-parser/commit/c79052b)) +* handle dot notation boolean options ([#63](https://github.com/yargs/yargs-parser/issues/63)) ([02c3545](https://github.com/yargs/yargs-parser/commit/02c3545)) + + + + +## [4.0.2](https://github.com/yargs/yargs-parser/compare/v4.0.1...v4.0.2) (2016-09-30) + + +### Bug Fixes + +* whoops, let's make the assign not change the Object key order ([29d069a](https://github.com/yargs/yargs-parser/commit/29d069a)) + + + + +## [4.0.1](https://github.com/yargs/yargs-parser/compare/v4.0.0...v4.0.1) (2016-09-30) + + +### Bug Fixes + +* lodash.assign was deprecated ([#59](https://github.com/yargs/yargs-parser/issues/59)) ([5e7eb11](https://github.com/yargs/yargs-parser/commit/5e7eb11)) + + + + +# [4.0.0](https://github.com/yargs/yargs-parser/compare/v3.2.0...v4.0.0) (2016-09-26) + + +### Bug Fixes + +* coerce should be applied to the final objects and arrays created ([#57](https://github.com/yargs/yargs-parser/issues/57)) ([4ca69da](https://github.com/yargs/yargs-parser/commit/4ca69da)) + + +### BREAKING CHANGES + +* coerce is no longer applied to individual arguments in an implicit array. + + + + +# [3.2.0](https://github.com/yargs/yargs-parser/compare/v3.1.0...v3.2.0) (2016-08-13) + + +### Features + +* coerce full array instead of each element ([#51](https://github.com/yargs/yargs-parser/issues/51)) ([cc4dc56](https://github.com/yargs/yargs-parser/commit/cc4dc56)) + + + + +# [3.1.0](https://github.com/yargs/yargs-parser/compare/v3.0.0...v3.1.0) (2016-08-09) + + +### Bug Fixes + +* address pkgConf parsing bug outlined in [#37](https://github.com/yargs/yargs-parser/issues/37) ([#45](https://github.com/yargs/yargs-parser/issues/45)) ([be76ee6](https://github.com/yargs/yargs-parser/commit/be76ee6)) +* better parsing of negative values ([#44](https://github.com/yargs/yargs-parser/issues/44)) ([2e43692](https://github.com/yargs/yargs-parser/commit/2e43692)) +* check aliases when guessing defaults for arguments fixes [#41](https://github.com/yargs/yargs-parser/issues/41) ([#43](https://github.com/yargs/yargs-parser/issues/43)) ([f3e4616](https://github.com/yargs/yargs-parser/commit/f3e4616)) + + +### Features + +* added coerce option, for providing specialized argument parsing ([#42](https://github.com/yargs/yargs-parser/issues/42)) ([7b49cd2](https://github.com/yargs/yargs-parser/commit/7b49cd2)) + + + + +# [3.0.0](https://github.com/yargs/yargs-parser/compare/v2.4.1...v3.0.0) (2016-08-07) + + +### Bug Fixes + +* parsing issue with numeric character in group of options ([#19](https://github.com/yargs/yargs-parser/issues/19)) ([f743236](https://github.com/yargs/yargs-parser/commit/f743236)) +* upgraded lodash.assign ([5d7fdf4](https://github.com/yargs/yargs-parser/commit/5d7fdf4)) + +### BREAKING CHANGES + +* subtle change to how values are parsed in a group of single-character arguments. +* _first released in 3.1.0, better handling of negative values should be considered a breaking change._ + + + + +## [2.4.1](https://github.com/yargs/yargs-parser/compare/v2.4.0...v2.4.1) (2016-07-16) + + +### Bug Fixes + +* **count:** do not increment a default value ([#39](https://github.com/yargs/yargs-parser/issues/39)) ([b04a189](https://github.com/yargs/yargs-parser/commit/b04a189)) + + + + +# [2.4.0](https://github.com/yargs/yargs-parser/compare/v2.3.0...v2.4.0) (2016-04-11) + + +### Features + +* **environment:** Support nested options in environment variables ([#26](https://github.com/yargs/yargs-parser/issues/26)) thanks [@elas7](https://github.com/elas7) \o/ ([020778b](https://github.com/yargs/yargs-parser/commit/020778b)) + + + + +# [2.3.0](https://github.com/yargs/yargs-parser/compare/v2.2.0...v2.3.0) (2016-04-09) + + +### Bug Fixes + +* **boolean:** fix for boolean options with non boolean defaults (#20) ([2dbe86b](https://github.com/yargs/yargs-parser/commit/2dbe86b)), closes [(#20](https://github.com/(/issues/20) +* **package:** remove tests from tarball ([0353c0d](https://github.com/yargs/yargs-parser/commit/0353c0d)) +* **parsing:** handle calling short option with an empty string as the next value. ([a867165](https://github.com/yargs/yargs-parser/commit/a867165)) +* boolean flag when next value contains the strings 'true' or 'false'. ([69941a6](https://github.com/yargs/yargs-parser/commit/69941a6)) +* update dependencies; add standard-version bin for next release (#24) ([822d9d5](https://github.com/yargs/yargs-parser/commit/822d9d5)) + +### Features + +* **configuration:** Allow to pass configuration objects to yargs-parser ([0780900](https://github.com/yargs/yargs-parser/commit/0780900)) +* **normalize:** allow normalize to work with arrays ([e0eaa1a](https://github.com/yargs/yargs-parser/commit/e0eaa1a)) diff --git a/node_modules/yargs-parser/LICENSE.txt b/node_modules/yargs-parser/LICENSE.txt new file mode 100644 index 0000000..836440b --- /dev/null +++ b/node_modules/yargs-parser/LICENSE.txt @@ -0,0 +1,14 @@ +Copyright (c) 2016, Contributors + +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/yargs-parser/README.md b/node_modules/yargs-parser/README.md new file mode 100644 index 0000000..bae61c2 --- /dev/null +++ b/node_modules/yargs-parser/README.md @@ -0,0 +1,449 @@ +# yargs-parser + +[![Build Status](https://travis-ci.org/yargs/yargs-parser.svg)](https://travis-ci.org/yargs/yargs-parser) +[![NPM version](https://img.shields.io/npm/v/yargs-parser.svg)](https://www.npmjs.com/package/yargs-parser) +[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version) + + +The mighty option parser used by [yargs](https://github.com/yargs/yargs). + +visit the [yargs website](http://yargs.js.org/) for more examples, and thorough usage instructions. + + + +## Example + +```sh +npm i yargs-parser --save +``` + +```js +var argv = require('yargs-parser')(process.argv.slice(2)) +console.log(argv) +``` + +```sh +node example.js --foo=33 --bar hello +{ _: [], foo: 33, bar: 'hello' } +``` + +_or parse a string!_ + +```js +var argv = require('yargs-parser')('--foo=99 --bar=33') +console.log(argv) +``` + +```sh +{ _: [], foo: 99, bar: 33 } +``` + +Convert an array of mixed types before passing to `yargs-parser`: + +```js +var parse = require('yargs-parser') +parse(['-f', 11, '--zoom', 55].join(' ')) // <-- array to string +parse(['-f', 11, '--zoom', 55].map(String)) // <-- array of strings +``` + +## API + +### require('yargs-parser')(args, opts={}) + +Parses command line arguments returning a simple mapping of keys and values. + +**expects:** + +* `args`: a string or array of strings representing the options to parse. +* `opts`: provide a set of hints indicating how `args` should be parsed: + * `opts.alias`: an object representing the set of aliases for a key: `{alias: {foo: ['f']}}`. + * `opts.array`: indicate that keys should be parsed as an array: `{array: ['foo', 'bar']}`.
+ Indicate that keys should be parsed as an array and coerced to booleans / numbers:
+ `{array: [{ key: 'foo', boolean: true }, {key: 'bar', number: true}]}`. + * `opts.boolean`: arguments should be parsed as booleans: `{boolean: ['x', 'y']}`. + * `opts.coerce`: provide a custom synchronous function that returns a coerced value from the argument provided + (or throws an error). For arrays the function is called only once for the entire array:
+ `{coerce: {foo: function (arg) {return modifiedArg}}}`. + * `opts.config`: indicate a key that represents a path to a configuration file (this file will be loaded and parsed). + * `opts.configObjects`: configuration objects to parse, their properties will be set as arguments:
+ `{configObjects: [{'x': 5, 'y': 33}, {'z': 44}]}`. + * `opts.configuration`: provide configuration options to the yargs-parser (see: [configuration](#configuration)). + * `opts.count`: indicate a key that should be used as a counter, e.g., `-vvv` = `{v: 3}`. + * `opts.default`: provide default values for keys: `{default: {x: 33, y: 'hello world!'}}`. + * `opts.envPrefix`: environment variables (`process.env`) with the prefix provided should be parsed. + * `opts.narg`: specify that a key requires `n` arguments: `{narg: {x: 2}}`. + * `opts.normalize`: `path.normalize()` will be applied to values set to this key. + * `opts.number`: keys should be treated as numbers. + * `opts.string`: keys should be treated as strings (even if they resemble a number `-x 33`). + +**returns:** + +* `obj`: an object representing the parsed value of `args` + * `key/value`: key value pairs for each argument and their aliases. + * `_`: an array representing the positional arguments. + * [optional] `--`: an array with arguments after the end-of-options flag `--`. + +### require('yargs-parser').detailed(args, opts={}) + +Parses a command line string, returning detailed information required by the +yargs engine. + +**expects:** + +* `args`: a string or array of strings representing options to parse. +* `opts`: provide a set of hints indicating how `args`, inputs are identical to `require('yargs-parser')(args, opts={})`. + +**returns:** + +* `argv`: an object representing the parsed value of `args` + * `key/value`: key value pairs for each argument and their aliases. + * `_`: an array representing the positional arguments. + * [optional] `--`: an array with arguments after the end-of-options flag `--`. +* `error`: populated with an error object if an exception occurred during parsing. +* `aliases`: the inferred list of aliases built by combining lists in `opts.alias`. +* `newAliases`: any new aliases added via camel-case expansion: + * `boolean`: `{ fooBar: true }` +* `defaulted`: any new argument created by `opts.default`, no aliases included. + * `boolean`: `{ foo: true }` +* `configuration`: given by default settings and `opts.configuration`. + + + +### Configuration + +The yargs-parser applies several automated transformations on the keys provided +in `args`. These features can be turned on and off using the `configuration` field +of `opts`. + +```js +var parsed = parser(['--no-dice'], { + configuration: { + 'boolean-negation': false + } +}) +``` + +### short option groups + +* default: `true`. +* key: `short-option-groups`. + +Should a group of short-options be treated as boolean flags? + +```sh +node example.js -abc +{ _: [], a: true, b: true, c: true } +``` + +_if disabled:_ + +```sh +node example.js -abc +{ _: [], abc: true } +``` + +### camel-case expansion + +* default: `true`. +* key: `camel-case-expansion`. + +Should hyphenated arguments be expanded into camel-case aliases? + +```sh +node example.js --foo-bar +{ _: [], 'foo-bar': true, fooBar: true } +``` + +_if disabled:_ + +```sh +node example.js --foo-bar +{ _: [], 'foo-bar': true } +``` + +### dot-notation + +* default: `true` +* key: `dot-notation` + +Should keys that contain `.` be treated as objects? + +```sh +node example.js --foo.bar +{ _: [], foo: { bar: true } } +``` + +_if disabled:_ + +```sh +node example.js --foo.bar +{ _: [], "foo.bar": true } +``` + +### parse numbers + +* default: `true` +* key: `parse-numbers` + +Should keys that look like numbers be treated as such? + +```sh +node example.js --foo=99.3 +{ _: [], foo: 99.3 } +``` + +_if disabled:_ + +```sh +node example.js --foo=99.3 +{ _: [], foo: "99.3" } +``` + +### boolean negation + +* default: `true` +* key: `boolean-negation` + +Should variables prefixed with `--no` be treated as negations? + +```sh +node example.js --no-foo +{ _: [], foo: false } +``` + +_if disabled:_ + +```sh +node example.js --no-foo +{ _: [], "no-foo": true } +``` + +### combine arrays + +* default: `false` +* key: `combine-arrays` + +Should arrays be combined when provided by both command line arguments and +a configuration file. + +### duplicate arguments array + +* default: `true` +* key: `duplicate-arguments-array` + +Should arguments be coerced into an array when duplicated: + +```sh +node example.js -x 1 -x 2 +{ _: [], x: [1, 2] } +``` + +_if disabled:_ + +```sh +node example.js -x 1 -x 2 +{ _: [], x: 2 } +``` + +### flatten duplicate arrays + +* default: `true` +* key: `flatten-duplicate-arrays` + +Should array arguments be coerced into a single array when duplicated: + +```sh +node example.js -x 1 2 -x 3 4 +{ _: [], x: [1, 2, 3, 4] } +``` + +_if disabled:_ + +```sh +node example.js -x 1 2 -x 3 4 +{ _: [], x: [[1, 2], [3, 4]] } +``` + +### greedy arrays + +* default: `true` +* key: `greedy-arrays` + +Should arrays consume more than one positional argument following their flag. + +```sh +node example --arr 1 2 +{ _[], arr: [1, 2] } +``` + +_if disabled:_ + +```sh +node example --arr 1 2 +{ _[2], arr: [1] } +``` + +**Note: in `v18.0.0` we are considering defaulting greedy arrays to `false`.** + +### nargs eats options + +* default: `false` +* key: `nargs-eats-options` + +Should nargs consume dash options as well as positional arguments. + +### negation prefix + +* default: `no-` +* key: `negation-prefix` + +The prefix to use for negated boolean variables. + +```sh +node example.js --no-foo +{ _: [], foo: false } +``` + +_if set to `quux`:_ + +```sh +node example.js --quuxfoo +{ _: [], foo: false } +``` + +### populate -- + +* default: `false`. +* key: `populate--` + +Should unparsed flags be stored in `--` or `_`. + +_If disabled:_ + +```sh +node example.js a -b -- x y +{ _: [ 'a', 'x', 'y' ], b: true } +``` + +_If enabled:_ + +```sh +node example.js a -b -- x y +{ _: [ 'a' ], '--': [ 'x', 'y' ], b: true } +``` + +### set placeholder key + +* default: `false`. +* key: `set-placeholder-key`. + +Should a placeholder be added for keys not set via the corresponding CLI argument? + +_If disabled:_ + +```sh +node example.js -a 1 -c 2 +{ _: [], a: 1, c: 2 } +``` + +_If enabled:_ + +```sh +node example.js -a 1 -c 2 +{ _: [], a: 1, b: undefined, c: 2 } +``` + +### halt at non-option + +* default: `false`. +* key: `halt-at-non-option`. + +Should parsing stop at the first positional argument? This is similar to how e.g. `ssh` parses its command line. + +_If disabled:_ + +```sh +node example.js -a run b -x y +{ _: [ 'b' ], a: 'run', x: 'y' } +``` + +_If enabled:_ + +```sh +node example.js -a run b -x y +{ _: [ 'b', '-x', 'y' ], a: 'run' } +``` + +### strip aliased + +* default: `false` +* key: `strip-aliased` + +Should aliases be removed before returning results? + +_If disabled:_ + +```sh +node example.js --test-field 1 +{ _: [], 'test-field': 1, testField: 1, 'test-alias': 1, testAlias: 1 } +``` + +_If enabled:_ + +```sh +node example.js --test-field 1 +{ _: [], 'test-field': 1, testField: 1 } +``` + +### strip dashed + +* default: `false` +* key: `strip-dashed` + +Should dashed keys be removed before returning results? This option has no effect if +`camel-case-expansion` is disabled. + +_If disabled:_ + +```sh +node example.js --test-field 1 +{ _: [], 'test-field': 1, testField: 1 } +``` + +_If enabled:_ + +```sh +node example.js --test-field 1 +{ _: [], testField: 1 } +``` + +### unknown options as args + +* default: `false` +* key: `unknown-options-as-args` + +Should unknown options be treated like regular arguments? An unknown option is one that is not +configured in `opts`. + +_If disabled_ + +```sh +node example.js --unknown-option --known-option 2 --string-option --unknown-option2 +{ _: [], unknownOption: true, knownOption: 2, stringOption: '', unknownOption2: true } +``` + +_If enabled_ + +```sh +node example.js --unknown-option --known-option 2 --string-option --unknown-option2 +{ _: ['--unknown-option'], knownOption: 2, stringOption: '--unknown-option2' } +``` + +## Special Thanks + +The yargs project evolves from optimist and minimist. It owes its +existence to a lot of James Halliday's hard work. Thanks [substack](https://github.com/substack) **beep** **boop** \o/ + +## License + +ISC diff --git a/node_modules/yargs-parser/index.js b/node_modules/yargs-parser/index.js new file mode 100644 index 0000000..c14c1fc --- /dev/null +++ b/node_modules/yargs-parser/index.js @@ -0,0 +1,1032 @@ +const camelCase = require('camelcase') +const decamelize = require('decamelize') +const path = require('path') +const tokenizeArgString = require('./lib/tokenize-arg-string') +const util = require('util') + +function parse (args, opts) { + opts = Object.assign(Object.create(null), opts) + // allow a string argument to be passed in rather + // than an argv array. + args = tokenizeArgString(args) + + // aliases might have transitive relationships, normalize this. + const aliases = combineAliases(Object.assign(Object.create(null), opts.alias)) + const configuration = Object.assign({ + 'boolean-negation': true, + 'camel-case-expansion': true, + 'combine-arrays': false, + 'dot-notation': true, + 'duplicate-arguments-array': true, + 'flatten-duplicate-arrays': true, + 'greedy-arrays': true, + 'halt-at-non-option': false, + 'nargs-eats-options': false, + 'negation-prefix': 'no-', + 'parse-numbers': true, + 'populate--': false, + 'set-placeholder-key': false, + 'short-option-groups': true, + 'strip-aliased': false, + 'strip-dashed': false, + 'unknown-options-as-args': false + }, opts.configuration) + const defaults = Object.assign(Object.create(null), opts.default) + const configObjects = opts.configObjects || [] + const envPrefix = opts.envPrefix + const notFlagsOption = configuration['populate--'] + const notFlagsArgv = notFlagsOption ? '--' : '_' + const newAliases = Object.create(null) + const defaulted = Object.create(null) + // allow a i18n handler to be passed in, default to a fake one (util.format). + const __ = opts.__ || util.format + const flags = { + aliases: Object.create(null), + arrays: Object.create(null), + bools: Object.create(null), + strings: Object.create(null), + numbers: Object.create(null), + counts: Object.create(null), + normalize: Object.create(null), + configs: Object.create(null), + nargs: Object.create(null), + coercions: Object.create(null), + keys: [] + } + const negative = /^-([0-9]+(\.[0-9]+)?|\.[0-9]+)$/ + const negatedBoolean = new RegExp('^--' + configuration['negation-prefix'] + '(.+)') + + ;[].concat(opts.array).filter(Boolean).forEach(function (opt) { + const key = opt.key || opt + + // assign to flags[bools|strings|numbers] + const assignment = Object.keys(opt).map(function (key) { + return ({ + boolean: 'bools', + string: 'strings', + number: 'numbers' + })[key] + }).filter(Boolean).pop() + + // assign key to be coerced + if (assignment) { + flags[assignment][key] = true + } + + flags.arrays[key] = true + flags.keys.push(key) + }) + + ;[].concat(opts.boolean).filter(Boolean).forEach(function (key) { + flags.bools[key] = true + flags.keys.push(key) + }) + + ;[].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true + flags.keys.push(key) + }) + + ;[].concat(opts.number).filter(Boolean).forEach(function (key) { + flags.numbers[key] = true + flags.keys.push(key) + }) + + ;[].concat(opts.count).filter(Boolean).forEach(function (key) { + flags.counts[key] = true + flags.keys.push(key) + }) + + ;[].concat(opts.normalize).filter(Boolean).forEach(function (key) { + flags.normalize[key] = true + flags.keys.push(key) + }) + + Object.keys(opts.narg || {}).forEach(function (k) { + flags.nargs[k] = opts.narg[k] + flags.keys.push(k) + }) + + Object.keys(opts.coerce || {}).forEach(function (k) { + flags.coercions[k] = opts.coerce[k] + flags.keys.push(k) + }) + + if (Array.isArray(opts.config) || typeof opts.config === 'string') { + ;[].concat(opts.config).filter(Boolean).forEach(function (key) { + flags.configs[key] = true + }) + } else { + Object.keys(opts.config || {}).forEach(function (k) { + flags.configs[k] = opts.config[k] + }) + } + + // create a lookup table that takes into account all + // combinations of aliases: {f: ['foo'], foo: ['f']} + extendAliases(opts.key, aliases, opts.default, flags.arrays) + + // apply default values to all aliases. + Object.keys(defaults).forEach(function (key) { + (flags.aliases[key] || []).forEach(function (alias) { + defaults[alias] = defaults[key] + }) + }) + + let error = null + checkConfiguration() + + let notFlags = [] + + const argv = Object.assign(Object.create(null), { _: [] }) + // TODO(bcoe): for the first pass at removing object prototype we didn't + // remove all prototypes from objects returned by this API, we might want + // to gradually move towards doing so. + const argvReturn = {} + + for (let i = 0; i < args.length; i++) { + const arg = args[i] + let broken + let key + let letters + let m + let next + let value + + // any unknown option (except for end-of-options, "--") + if (arg !== '--' && isUnknownOptionAsArg(arg)) { + argv._.push(arg) + // -- separated by = + } else if (arg.match(/^--.+=/) || ( + !configuration['short-option-groups'] && arg.match(/^-.+=/) + )) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + m = arg.match(/^--?([^=]+)=([\s\S]*)$/) + + // arrays format = '--f=a b c' + if (checkAllAliases(m[1], flags.arrays)) { + i = eatArray(i, m[1], args, m[2]) + } else if (checkAllAliases(m[1], flags.nargs) !== false) { + // nargs format = '--f=monkey washing cat' + i = eatNargs(i, m[1], args, m[2]) + } else { + setArg(m[1], m[2]) + } + } else if (arg.match(negatedBoolean) && configuration['boolean-negation']) { + key = arg.match(negatedBoolean)[1] + setArg(key, checkAllAliases(key, flags.arrays) ? [false] : false) + + // -- separated by space. + } else if (arg.match(/^--.+/) || ( + !configuration['short-option-groups'] && arg.match(/^-[^-]+/) + )) { + key = arg.match(/^--?(.+)/)[1] + + if (checkAllAliases(key, flags.arrays)) { + // array format = '--foo a b c' + i = eatArray(i, key, args) + } else if (checkAllAliases(key, flags.nargs) !== false) { + // nargs format = '--foo a b c' + // should be truthy even if: flags.nargs[key] === 0 + i = eatNargs(i, key, args) + } else { + next = args[i + 1] + + if (next !== undefined && (!next.match(/^-/) || + next.match(negative)) && + !checkAllAliases(key, flags.bools) && + !checkAllAliases(key, flags.counts)) { + setArg(key, next) + i++ + } else if (/^(true|false)$/.test(next)) { + setArg(key, next) + i++ + } else { + setArg(key, defaultValue(key)) + } + } + + // dot-notation flag separated by '='. + } else if (arg.match(/^-.\..+=/)) { + m = arg.match(/^-([^=]+)=([\s\S]*)$/) + setArg(m[1], m[2]) + + // dot-notation flag separated by space. + } else if (arg.match(/^-.\..+/) && !arg.match(negative)) { + next = args[i + 1] + key = arg.match(/^-(.\..+)/)[1] + + if (next !== undefined && !next.match(/^-/) && + !checkAllAliases(key, flags.bools) && + !checkAllAliases(key, flags.counts)) { + setArg(key, next) + i++ + } else { + setArg(key, defaultValue(key)) + } + } else if (arg.match(/^-[^-]+/) && !arg.match(negative)) { + letters = arg.slice(1, -1).split('') + broken = false + + for (let j = 0; j < letters.length; j++) { + next = arg.slice(j + 2) + + if (letters[j + 1] && letters[j + 1] === '=') { + value = arg.slice(j + 3) + key = letters[j] + + if (checkAllAliases(key, flags.arrays)) { + // array format = '-f=a b c' + i = eatArray(i, key, args, value) + } else if (checkAllAliases(key, flags.nargs) !== false) { + // nargs format = '-f=monkey washing cat' + i = eatNargs(i, key, args, value) + } else { + setArg(key, value) + } + + broken = true + break + } + + if (next === '-') { + setArg(letters[j], next) + continue + } + + // current letter is an alphabetic character and next value is a number + if (/[A-Za-z]/.test(letters[j]) && + /^-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { + setArg(letters[j], next) + broken = true + break + } + + if (letters[j + 1] && letters[j + 1].match(/\W/)) { + setArg(letters[j], next) + broken = true + break + } else { + setArg(letters[j], defaultValue(letters[j])) + } + } + + key = arg.slice(-1)[0] + + if (!broken && key !== '-') { + if (checkAllAliases(key, flags.arrays)) { + // array format = '-f a b c' + i = eatArray(i, key, args) + } else if (checkAllAliases(key, flags.nargs) !== false) { + // nargs format = '-f a b c' + // should be truthy even if: flags.nargs[key] === 0 + i = eatNargs(i, key, args) + } else { + next = args[i + 1] + + if (next !== undefined && (!/^(-|--)[^-]/.test(next) || + next.match(negative)) && + !checkAllAliases(key, flags.bools) && + !checkAllAliases(key, flags.counts)) { + setArg(key, next) + i++ + } else if (/^(true|false)$/.test(next)) { + setArg(key, next) + i++ + } else { + setArg(key, defaultValue(key)) + } + } + } + } else if (arg.match(/^-[0-9]$/) && + arg.match(negative) && + checkAllAliases(arg.slice(1), flags.bools)) { + // single-digit boolean alias, e.g: xargs -0 + key = arg.slice(1) + setArg(key, defaultValue(key)) + } else if (arg === '--') { + notFlags = args.slice(i + 1) + break + } else if (configuration['halt-at-non-option']) { + notFlags = args.slice(i) + break + } else { + argv._.push(maybeCoerceNumber('_', arg)) + } + } + + // order of precedence: + // 1. command line arg + // 2. value from env var + // 3. value from config file + // 4. value from config objects + // 5. configured default value + applyEnvVars(argv, true) // special case: check env vars that point to config file + applyEnvVars(argv, false) + setConfig(argv) + setConfigObjects() + applyDefaultsAndAliases(argv, flags.aliases, defaults, true) + applyCoercions(argv) + if (configuration['set-placeholder-key']) setPlaceholderKeys(argv) + + // for any counts either not in args or without an explicit default, set to 0 + Object.keys(flags.counts).forEach(function (key) { + if (!hasKey(argv, key.split('.'))) setArg(key, 0) + }) + + // '--' defaults to undefined. + if (notFlagsOption && notFlags.length) argv[notFlagsArgv] = [] + notFlags.forEach(function (key) { + argv[notFlagsArgv].push(key) + }) + + if (configuration['camel-case-expansion'] && configuration['strip-dashed']) { + Object.keys(argv).filter(key => key !== '--' && key.includes('-')).forEach(key => { + delete argv[key] + }) + } + + if (configuration['strip-aliased']) { + ;[].concat(...Object.keys(aliases).map(k => aliases[k])).forEach(alias => { + if (configuration['camel-case-expansion']) { + delete argv[alias.split('.').map(prop => camelCase(prop)).join('.')] + } + + delete argv[alias] + }) + } + + // how many arguments should we consume, based + // on the nargs option? + function eatNargs (i, key, args, argAfterEqualSign) { + let ii + let toEat = checkAllAliases(key, flags.nargs) + // NaN has a special meaning for the array type, indicating that one or + // more values are expected. + toEat = isNaN(toEat) ? 1 : toEat + + if (toEat === 0) { + if (!isUndefined(argAfterEqualSign)) { + error = Error(__('Argument unexpected for: %s', key)) + } + setArg(key, defaultValue(key)) + return i + } + + let available = isUndefined(argAfterEqualSign) ? 0 : 1 + if (configuration['nargs-eats-options']) { + // classic behavior, yargs eats positional and dash arguments. + if (args.length - (i + 1) + available < toEat) { + error = Error(__('Not enough arguments following: %s', key)) + } + available = toEat + } else { + // nargs will not consume flag arguments, e.g., -abc, --foo, + // and terminates when one is observed. + for (ii = i + 1; ii < args.length; ii++) { + if (!args[ii].match(/^-[^0-9]/) || args[ii].match(negative) || isUnknownOptionAsArg(args[ii])) available++ + else break + } + if (available < toEat) error = Error(__('Not enough arguments following: %s', key)) + } + + let consumed = Math.min(available, toEat) + if (!isUndefined(argAfterEqualSign) && consumed > 0) { + setArg(key, argAfterEqualSign) + consumed-- + } + for (ii = i + 1; ii < (consumed + i + 1); ii++) { + setArg(key, args[ii]) + } + + return (i + consumed) + } + + // if an option is an array, eat all non-hyphenated arguments + // following it... YUM! + // e.g., --foo apple banana cat becomes ["apple", "banana", "cat"] + function eatArray (i, key, args, argAfterEqualSign) { + let argsToSet = [] + let next = argAfterEqualSign || args[i + 1] + // If both array and nargs are configured, enforce the nargs count: + const nargsCount = checkAllAliases(key, flags.nargs) + + if (checkAllAliases(key, flags.bools) && !(/^(true|false)$/.test(next))) { + argsToSet.push(true) + } else if (isUndefined(next) || + (isUndefined(argAfterEqualSign) && /^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next))) { + // for keys without value ==> argsToSet remains an empty [] + // set user default value, if available + if (defaults[key] !== undefined) { + const defVal = defaults[key] + argsToSet = Array.isArray(defVal) ? defVal : [defVal] + } + } else { + // value in --option=value is eaten as is + if (!isUndefined(argAfterEqualSign)) { + argsToSet.push(processValue(key, argAfterEqualSign)) + } + for (let ii = i + 1; ii < args.length; ii++) { + if ((!configuration['greedy-arrays'] && argsToSet.length > 0) || + (nargsCount && argsToSet.length >= nargsCount)) break + next = args[ii] + if (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next)) break + i = ii + argsToSet.push(processValue(key, next)) + } + } + + // If both array and nargs are configured, create an error if less than + // nargs positionals were found. NaN has special meaning, indicating + // that at least one value is required (more are okay). + if ((nargsCount && argsToSet.length < nargsCount) || + (isNaN(nargsCount) && argsToSet.length === 0)) { + error = Error(__('Not enough arguments following: %s', key)) + } + + setArg(key, argsToSet) + return i + } + + function setArg (key, val) { + if (/-/.test(key) && configuration['camel-case-expansion']) { + const alias = key.split('.').map(function (prop) { + return camelCase(prop) + }).join('.') + addNewAlias(key, alias) + } + + const value = processValue(key, val) + const splitKey = key.split('.') + setKey(argv, splitKey, value) + + // handle populating aliases of the full key + if (flags.aliases[key]) { + flags.aliases[key].forEach(function (x) { + x = x.split('.') + setKey(argv, x, value) + }) + } + + // handle populating aliases of the first element of the dot-notation key + if (splitKey.length > 1 && configuration['dot-notation']) { + ;(flags.aliases[splitKey[0]] || []).forEach(function (x) { + x = x.split('.') + + // expand alias with nested objects in key + const a = [].concat(splitKey) + a.shift() // nuke the old key. + x = x.concat(a) + + // populate alias only if is not already an alias of the full key + // (already populated above) + if (!(flags.aliases[key] || []).includes(x.join('.'))) { + setKey(argv, x, value) + } + }) + } + + // Set normalize getter and setter when key is in 'normalize' but isn't an array + if (checkAllAliases(key, flags.normalize) && !checkAllAliases(key, flags.arrays)) { + const keys = [key].concat(flags.aliases[key] || []) + keys.forEach(function (key) { + Object.defineProperty(argvReturn, key, { + enumerable: true, + get () { + return val + }, + set (value) { + val = typeof value === 'string' ? path.normalize(value) : value + } + }) + }) + } + } + + function addNewAlias (key, alias) { + if (!(flags.aliases[key] && flags.aliases[key].length)) { + flags.aliases[key] = [alias] + newAliases[alias] = true + } + if (!(flags.aliases[alias] && flags.aliases[alias].length)) { + addNewAlias(alias, key) + } + } + + function processValue (key, val) { + // strings may be quoted, clean this up as we assign values. + if (typeof val === 'string' && + (val[0] === "'" || val[0] === '"') && + val[val.length - 1] === val[0] + ) { + val = val.substring(1, val.length - 1) + } + + // handle parsing boolean arguments --foo=true --bar false. + if (checkAllAliases(key, flags.bools) || checkAllAliases(key, flags.counts)) { + if (typeof val === 'string') val = val === 'true' + } + + let value = Array.isArray(val) + ? val.map(function (v) { return maybeCoerceNumber(key, v) }) + : maybeCoerceNumber(key, val) + + // increment a count given as arg (either no value or value parsed as boolean) + if (checkAllAliases(key, flags.counts) && (isUndefined(value) || typeof value === 'boolean')) { + value = increment + } + + // Set normalized value when key is in 'normalize' and in 'arrays' + if (checkAllAliases(key, flags.normalize) && checkAllAliases(key, flags.arrays)) { + if (Array.isArray(val)) value = val.map(path.normalize) + else value = path.normalize(val) + } + return value + } + + function maybeCoerceNumber (key, value) { + if (!checkAllAliases(key, flags.strings) && !checkAllAliases(key, flags.bools) && !Array.isArray(value)) { + const shouldCoerceNumber = isNumber(value) && configuration['parse-numbers'] && ( + Number.isSafeInteger(Math.floor(value)) + ) + if (shouldCoerceNumber || (!isUndefined(value) && checkAllAliases(key, flags.numbers))) value = Number(value) + } + return value + } + + // set args from config.json file, this should be + // applied last so that defaults can be applied. + function setConfig (argv) { + const configLookup = Object.create(null) + + // expand defaults/aliases, in-case any happen to reference + // the config.json file. + applyDefaultsAndAliases(configLookup, flags.aliases, defaults) + + Object.keys(flags.configs).forEach(function (configKey) { + const configPath = argv[configKey] || configLookup[configKey] + if (configPath) { + try { + let config = null + const resolvedConfigPath = path.resolve(process.cwd(), configPath) + + if (typeof flags.configs[configKey] === 'function') { + try { + config = flags.configs[configKey](resolvedConfigPath) + } catch (e) { + config = e + } + if (config instanceof Error) { + error = config + return + } + } else { + config = require(resolvedConfigPath) + } + + setConfigObject(config) + } catch (ex) { + if (argv[configKey]) error = Error(__('Invalid JSON config file: %s', configPath)) + } + } + }) + } + + // set args from config object. + // it recursively checks nested objects. + function setConfigObject (config, prev) { + Object.keys(config).forEach(function (key) { + const value = config[key] + const fullKey = prev ? prev + '.' + key : key + + // if the value is an inner object and we have dot-notation + // enabled, treat inner objects in config the same as + // heavily nested dot notations (foo.bar.apple). + if (typeof value === 'object' && value !== null && !Array.isArray(value) && configuration['dot-notation']) { + // if the value is an object but not an array, check nested object + setConfigObject(value, fullKey) + } else { + // setting arguments via CLI takes precedence over + // values within the config file. + if (!hasKey(argv, fullKey.split('.')) || (checkAllAliases(fullKey, flags.arrays) && configuration['combine-arrays'])) { + setArg(fullKey, value) + } + } + }) + } + + // set all config objects passed in opts + function setConfigObjects () { + if (typeof configObjects === 'undefined') return + configObjects.forEach(function (configObject) { + setConfigObject(configObject) + }) + } + + function applyEnvVars (argv, configOnly) { + if (typeof envPrefix === 'undefined') return + + const prefix = typeof envPrefix === 'string' ? envPrefix : '' + Object.keys(process.env).forEach(function (envVar) { + if (prefix === '' || envVar.lastIndexOf(prefix, 0) === 0) { + // get array of nested keys and convert them to camel case + const keys = envVar.split('__').map(function (key, i) { + if (i === 0) { + key = key.substring(prefix.length) + } + return camelCase(key) + }) + + if (((configOnly && flags.configs[keys.join('.')]) || !configOnly) && !hasKey(argv, keys)) { + setArg(keys.join('.'), process.env[envVar]) + } + } + }) + } + + function applyCoercions (argv) { + let coerce + const applied = new Set() + Object.keys(argv).forEach(function (key) { + if (!applied.has(key)) { // If we haven't already coerced this option via one of its aliases + coerce = checkAllAliases(key, flags.coercions) + if (typeof coerce === 'function') { + try { + const value = maybeCoerceNumber(key, coerce(argv[key])) + ;([].concat(flags.aliases[key] || [], key)).forEach(ali => { + applied.add(ali) + argv[ali] = value + }) + } catch (err) { + error = err + } + } + } + }) + } + + function setPlaceholderKeys (argv) { + flags.keys.forEach((key) => { + // don't set placeholder keys for dot notation options 'foo.bar'. + if (~key.indexOf('.')) return + if (typeof argv[key] === 'undefined') argv[key] = undefined + }) + return argv + } + + function applyDefaultsAndAliases (obj, aliases, defaults, canLog = false) { + Object.keys(defaults).forEach(function (key) { + if (!hasKey(obj, key.split('.'))) { + setKey(obj, key.split('.'), defaults[key]) + if (canLog) defaulted[key] = true + + ;(aliases[key] || []).forEach(function (x) { + if (hasKey(obj, x.split('.'))) return + setKey(obj, x.split('.'), defaults[key]) + }) + } + }) + } + + function hasKey (obj, keys) { + let o = obj + + if (!configuration['dot-notation']) keys = [keys.join('.')] + + keys.slice(0, -1).forEach(function (key) { + o = (o[key] || {}) + }) + + const key = keys[keys.length - 1] + + if (typeof o !== 'object') return false + else return key in o + } + + function setKey (obj, keys, value) { + let o = obj + + if (!configuration['dot-notation']) keys = [keys.join('.')] + + keys.slice(0, -1).forEach(function (key, index) { + // TODO(bcoe): in the next major version of yargs, switch to + // Object.create(null) for dot notation: + key = sanitizeKey(key) + + if (typeof o === 'object' && o[key] === undefined) { + o[key] = {} + } + + if (typeof o[key] !== 'object' || Array.isArray(o[key])) { + // ensure that o[key] is an array, and that the last item is an empty object. + if (Array.isArray(o[key])) { + o[key].push({}) + } else { + o[key] = [o[key], {}] + } + + // we want to update the empty object at the end of the o[key] array, so set o to that object + o = o[key][o[key].length - 1] + } else { + o = o[key] + } + }) + + // TODO(bcoe): in the next major version of yargs, switch to + // Object.create(null) for dot notation: + const key = sanitizeKey(keys[keys.length - 1]) + + const isTypeArray = checkAllAliases(keys.join('.'), flags.arrays) + const isValueArray = Array.isArray(value) + let duplicate = configuration['duplicate-arguments-array'] + + // nargs has higher priority than duplicate + if (!duplicate && checkAllAliases(key, flags.nargs)) { + duplicate = true + if ((!isUndefined(o[key]) && flags.nargs[key] === 1) || (Array.isArray(o[key]) && o[key].length === flags.nargs[key])) { + o[key] = undefined + } + } + + if (value === increment) { + o[key] = increment(o[key]) + } else if (Array.isArray(o[key])) { + if (duplicate && isTypeArray && isValueArray) { + o[key] = configuration['flatten-duplicate-arrays'] ? o[key].concat(value) : (Array.isArray(o[key][0]) ? o[key] : [o[key]]).concat([value]) + } else if (!duplicate && Boolean(isTypeArray) === Boolean(isValueArray)) { + o[key] = value + } else { + o[key] = o[key].concat([value]) + } + } else if (o[key] === undefined && isTypeArray) { + o[key] = isValueArray ? value : [value] + } else if (duplicate && !( + o[key] === undefined || + checkAllAliases(key, flags.counts) || + checkAllAliases(key, flags.bools) + )) { + o[key] = [o[key], value] + } else { + o[key] = value + } + } + + // extend the aliases list with inferred aliases. + function extendAliases (...args) { + args.forEach(function (obj) { + Object.keys(obj || {}).forEach(function (key) { + // short-circuit if we've already added a key + // to the aliases array, for example it might + // exist in both 'opts.default' and 'opts.key'. + if (flags.aliases[key]) return + + flags.aliases[key] = [].concat(aliases[key] || []) + // For "--option-name", also set argv.optionName + flags.aliases[key].concat(key).forEach(function (x) { + if (/-/.test(x) && configuration['camel-case-expansion']) { + const c = camelCase(x) + if (c !== key && flags.aliases[key].indexOf(c) === -1) { + flags.aliases[key].push(c) + newAliases[c] = true + } + } + }) + // For "--optionName", also set argv['option-name'] + flags.aliases[key].concat(key).forEach(function (x) { + if (x.length > 1 && /[A-Z]/.test(x) && configuration['camel-case-expansion']) { + const c = decamelize(x, '-') + if (c !== key && flags.aliases[key].indexOf(c) === -1) { + flags.aliases[key].push(c) + newAliases[c] = true + } + } + }) + flags.aliases[key].forEach(function (x) { + flags.aliases[x] = [key].concat(flags.aliases[key].filter(function (y) { + return x !== y + })) + }) + }) + }) + } + + // return the 1st set flag for any of a key's aliases (or false if no flag set) + function checkAllAliases (key, flag) { + const toCheck = [].concat(flags.aliases[key] || [], key) + const keys = Object.keys(flag) + const setAlias = toCheck.find(key => keys.includes(key)) + return setAlias ? flag[setAlias] : false + } + + function hasAnyFlag (key) { + const toCheck = [].concat(Object.keys(flags).map(k => flags[k])) + return toCheck.some(function (flag) { + return Array.isArray(flag) ? flag.includes(key) : flag[key] + }) + } + + function hasFlagsMatching (arg, ...patterns) { + const toCheck = [].concat(...patterns) + return toCheck.some(function (pattern) { + const match = arg.match(pattern) + return match && hasAnyFlag(match[1]) + }) + } + + // based on a simplified version of the short flag group parsing logic + function hasAllShortFlags (arg) { + // if this is a negative number, or doesn't start with a single hyphen, it's not a short flag group + if (arg.match(negative) || !arg.match(/^-[^-]+/)) { return false } + let hasAllFlags = true + let next + const letters = arg.slice(1).split('') + for (let j = 0; j < letters.length; j++) { + next = arg.slice(j + 2) + + if (!hasAnyFlag(letters[j])) { + hasAllFlags = false + break + } + + if ((letters[j + 1] && letters[j + 1] === '=') || + next === '-' || + (/[A-Za-z]/.test(letters[j]) && /^-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) || + (letters[j + 1] && letters[j + 1].match(/\W/))) { + break + } + } + return hasAllFlags + } + + function isUnknownOptionAsArg (arg) { + return configuration['unknown-options-as-args'] && isUnknownOption(arg) + } + + function isUnknownOption (arg) { + // ignore negative numbers + if (arg.match(negative)) { return false } + // if this is a short option group and all of them are configured, it isn't unknown + if (hasAllShortFlags(arg)) { return false } + // e.g. '--count=2' + const flagWithEquals = /^-+([^=]+?)=[\s\S]*$/ + // e.g. '-a' or '--arg' + const normalFlag = /^-+([^=]+?)$/ + // e.g. '-a-' + const flagEndingInHyphen = /^-+([^=]+?)-$/ + // e.g. '-abc123' + const flagEndingInDigits = /^-+([^=]+?\d+)$/ + // e.g. '-a/usr/local' + const flagEndingInNonWordCharacters = /^-+([^=]+?)\W+.*$/ + // check the different types of flag styles, including negatedBoolean, a pattern defined near the start of the parse method + return !hasFlagsMatching(arg, flagWithEquals, negatedBoolean, normalFlag, flagEndingInHyphen, flagEndingInDigits, flagEndingInNonWordCharacters) + } + + // make a best effor to pick a default value + // for an option based on name and type. + function defaultValue (key) { + if (!checkAllAliases(key, flags.bools) && + !checkAllAliases(key, flags.counts) && + `${key}` in defaults) { + return defaults[key] + } else { + return defaultForType(guessType(key)) + } + } + + // return a default value, given the type of a flag., + // e.g., key of type 'string' will default to '', rather than 'true'. + function defaultForType (type) { + const def = { + boolean: true, + string: '', + number: undefined, + array: [] + } + + return def[type] + } + + // given a flag, enforce a default type. + function guessType (key) { + let type = 'boolean' + if (checkAllAliases(key, flags.strings)) type = 'string' + else if (checkAllAliases(key, flags.numbers)) type = 'number' + else if (checkAllAliases(key, flags.bools)) type = 'boolean' + else if (checkAllAliases(key, flags.arrays)) type = 'array' + return type + } + + function isNumber (x) { + if (x === null || x === undefined) return false + // if loaded from config, may already be a number. + if (typeof x === 'number') return true + // hexadecimal. + if (/^0x[0-9a-f]+$/i.test(x)) return true + // don't treat 0123 as a number; as it drops the leading '0'. + if (x.length > 1 && x[0] === '0') return false + return /^[-]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x) + } + + function isUndefined (num) { + return num === undefined + } + + // check user configuration settings for inconsistencies + function checkConfiguration () { + // count keys should not be set as array/narg + Object.keys(flags.counts).find(key => { + if (checkAllAliases(key, flags.arrays)) { + error = Error(__('Invalid configuration: %s, opts.count excludes opts.array.', key)) + return true + } else if (checkAllAliases(key, flags.nargs)) { + error = Error(__('Invalid configuration: %s, opts.count excludes opts.narg.', key)) + return true + } + }) + } + + return { + argv: Object.assign(argvReturn, argv), + error: error, + aliases: Object.assign({}, flags.aliases), + newAliases: Object.assign({}, newAliases), + defaulted: Object.assign({}, defaulted), + configuration: configuration + } +} + +// if any aliases reference each other, we should +// merge them together. +function combineAliases (aliases) { + const aliasArrays = [] + const combined = Object.create(null) + let change = true + + // turn alias lookup hash {key: ['alias1', 'alias2']} into + // a simple array ['key', 'alias1', 'alias2'] + Object.keys(aliases).forEach(function (key) { + aliasArrays.push( + [].concat(aliases[key], key) + ) + }) + + // combine arrays until zero changes are + // made in an iteration. + while (change) { + change = false + for (let i = 0; i < aliasArrays.length; i++) { + for (let ii = i + 1; ii < aliasArrays.length; ii++) { + const intersect = aliasArrays[i].filter(function (v) { + return aliasArrays[ii].indexOf(v) !== -1 + }) + + if (intersect.length) { + aliasArrays[i] = aliasArrays[i].concat(aliasArrays[ii]) + aliasArrays.splice(ii, 1) + change = true + break + } + } + } + } + + // map arrays back to the hash-lookup (de-dupe while + // we're at it). + aliasArrays.forEach(function (aliasArray) { + aliasArray = aliasArray.filter(function (v, i, self) { + return self.indexOf(v) === i + }) + combined[aliasArray.pop()] = aliasArray + }) + + return combined +} + +// this function should only be called when a count is given as an arg +// it is NOT called to set a default value +// thus we can start the count at 1 instead of 0 +function increment (orig) { + return orig !== undefined ? orig + 1 : 1 +} + +function Parser (args, opts) { + const result = parse(args.slice(), opts) + return result.argv +} + +// parse arguments and return detailed +// meta information, aliases, etc. +Parser.detailed = function (args, opts) { + return parse(args.slice(), opts) +} + +// TODO(bcoe): in the next major version of yargs, switch to +// Object.create(null) for dot notation: +function sanitizeKey (key) { + if (key === '__proto__') return '___proto___' + return key +} + +module.exports = Parser diff --git a/node_modules/yargs-parser/lib/tokenize-arg-string.js b/node_modules/yargs-parser/lib/tokenize-arg-string.js new file mode 100644 index 0000000..260c67c --- /dev/null +++ b/node_modules/yargs-parser/lib/tokenize-arg-string.js @@ -0,0 +1,40 @@ +// take an un-split argv string and tokenize it. +module.exports = function (argString) { + if (Array.isArray(argString)) { + return argString.map(e => typeof e !== 'string' ? e + '' : e) + } + + argString = argString.trim() + + let i = 0 + let prevC = null + let c = null + let opening = null + const args = [] + + for (let ii = 0; ii < argString.length; ii++) { + prevC = c + c = argString.charAt(ii) + + // split on spaces unless we're in quotes. + if (c === ' ' && !opening) { + if (!(prevC === ' ')) { + i++ + } + continue + } + + // don't split the string if we're in matching + // opening or closing single and double quotes. + if (c === opening) { + opening = null + } else if ((c === "'" || c === '"') && !opening) { + opening = c + } + + if (!args[i]) args[i] = '' + args[i] += c + } + + return args +} diff --git a/node_modules/yargs-parser/package.json b/node_modules/yargs-parser/package.json new file mode 100644 index 0000000..636ff17 --- /dev/null +++ b/node_modules/yargs-parser/package.json @@ -0,0 +1,46 @@ +{ + "name": "yargs-parser", + "version": "18.1.3", + "description": "the mighty option parser used by yargs", + "main": "index.js", + "scripts": { + "fix": "standard --fix", + "test": "c8 --reporter=text --reporter=html mocha test/*.js", + "posttest": "standard", + "coverage": "c8 report --check-coverage check-coverage --lines=100 --branches=97 --statements=100" + }, + "repository": { + "type": "git", + "url": "https://github.com/yargs/yargs-parser.git" + }, + "keywords": [ + "argument", + "parser", + "yargs", + "command", + "cli", + "parsing", + "option", + "args", + "argument" + ], + "author": "Ben Coe ", + "license": "ISC", + "devDependencies": { + "c8": "^7.0.1", + "chai": "^4.2.0", + "mocha": "^7.0.0", + "standard": "^14.3.1" + }, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "files": [ + "lib", + "index.js" + ], + "engines": { + "node": ">=6" + } +} diff --git a/node_modules/yargs/CHANGELOG.md b/node_modules/yargs/CHANGELOG.md new file mode 100644 index 0000000..a010cf3 --- /dev/null +++ b/node_modules/yargs/CHANGELOG.md @@ -0,0 +1,420 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +## [15.4.0](https://www.github.com/yargs/yargs/compare/v15.3.1...v15.4.0) (2020-06-30) + + +### Features + +* adds deprecation option for commands ([027a636](https://www.github.com/yargs/yargs/commit/027a6365b737e13116811a8ef43670196e1fa00a)) +* support array of examples ([#1682](https://www.github.com/yargs/yargs/issues/1682)) ([225ab82](https://www.github.com/yargs/yargs/commit/225ab8271938bed3a48d23175f3d580ce8cd1306)) + + +### Bug Fixes + +* **docs:** describe usage of `.check()` in more detail ([932cd11](https://www.github.com/yargs/yargs/commit/932cd1177e93f5cc99edfe57a4028e30717bf8fb)) +* **i18n:** Japanese translation phrasing ([#1619](https://www.github.com/yargs/yargs/issues/1619)) ([0894175](https://www.github.com/yargs/yargs/commit/089417550ef5a5b8ce3578dd2a989191300b64cd)) +* **strict mode:** report default command unknown arguments ([#1626](https://www.github.com/yargs/yargs/issues/1626)) ([69f29a9](https://www.github.com/yargs/yargs/commit/69f29a9cd429d4bb99481238305390107ac75b02)) +* **usage:** translate 'options' group only when displaying help ([#1600](https://www.github.com/yargs/yargs/issues/1600)) ([e60b39b](https://www.github.com/yargs/yargs/commit/e60b39b9d3a912c06db43f87c86ba894142b6c1c)) + + +### Reverts + +* Revert "chore(deps): update dependency eslint to v7 (#1656)" (#1673) ([34949f8](https://www.github.com/yargs/yargs/commit/34949f89ee7cdf88f7b315659df4b5f62f714842)), closes [#1656](https://www.github.com/yargs/yargs/issues/1656) [#1673](https://www.github.com/yargs/yargs/issues/1673) + +### [15.3.1](https://www.github.com/yargs/yargs/compare/v15.3.0...v15.3.1) (2020-03-16) + + +### Bug Fixes + +* \_\_proto\_\_ will now be replaced with \_\_\_proto\_\_\_ in parse ([#258](https://www.github.com/yargs/yargs-parser/issues/258)), patching a potential +prototype pollution vulnerability. This was reported by the Snyk Security Research Team. ([63810ca](https://www.github.com/yargs/yargs-parser/commit/63810ca1ae1a24b08293a4d971e70e058c7a41e2)) + +## [15.3.0](https://www.github.com/yargs/yargs/compare/v15.2.0...v15.3.0) (2020-03-08) + + +### Features + +* **yargs-parser:** introduce single-digit boolean aliases ([#1576](https://www.github.com/yargs/yargs/issues/1576)) ([3af7f04](https://www.github.com/yargs/yargs/commit/3af7f04cdbfcbd4b3f432aca5144d43f21958c39)) +* add usage for single-digit boolean aliases ([#1580](https://www.github.com/yargs/yargs/issues/1580)) ([6014e39](https://www.github.com/yargs/yargs/commit/6014e39bca3a1e8445aa0fb2a435f6181e344c45)) + + +### Bug Fixes + +* address ambiguity between nargs of 1 and requiresArg ([#1572](https://www.github.com/yargs/yargs/issues/1572)) ([a5edc32](https://www.github.com/yargs/yargs/commit/a5edc328ecb3f90d1ba09cfe70a0040f68adf50a)) + +## [15.2.0](https://www.github.com/yargs/yargs/compare/v15.1.0...v15.2.0) (2020-03-01) + + +### ⚠ BREAKING CHANGES + +* **deps:** yargs-parser@17.0.0 no longer implicitly creates arrays out of boolean +arguments when duplicates are provided + +### Features + +* **completion:** takes negated flags into account when boolean-negation is set ([#1509](https://www.github.com/yargs/yargs/issues/1509)) ([7293ad5](https://www.github.com/yargs/yargs/commit/7293ad50d20ea0fb7dd1ac9b925e90e1bd95dea8)) +* **deps:** pull in yargs-parser@17.0.0 ([#1553](https://www.github.com/yargs/yargs/issues/1553)) ([b9409da](https://www.github.com/yargs/yargs/commit/b9409da199ebca515a848489c206b807fab2e65d)) +* deprecateOption ([#1559](https://www.github.com/yargs/yargs/issues/1559)) ([8aae333](https://www.github.com/yargs/yargs/commit/8aae3332251d09fa136db17ef4a40d83fa052bc4)) +* display appropriate $0 for electron apps ([#1536](https://www.github.com/yargs/yargs/issues/1536)) ([d0e4379](https://www.github.com/yargs/yargs/commit/d0e437912917d6a66bb5128992fa2f566a5f830b)) +* introduces strictCommands() subset of strict mode ([#1540](https://www.github.com/yargs/yargs/issues/1540)) ([1d4cca3](https://www.github.com/yargs/yargs/commit/1d4cca395a98b395e6318f0505fc73bef8b01350)) +* **deps:** yargs-parser with 'greedy-array' configuration ([#1569](https://www.github.com/yargs/yargs/issues/1569)) ([a03a320](https://www.github.com/yargs/yargs/commit/a03a320dbf5c0ce33d829a857fc04a651c0bb53e)) + + +### Bug Fixes + +* help always displayed for the first command parsed having an async handler ([#1535](https://www.github.com/yargs/yargs/issues/1535)) ([d585b30](https://www.github.com/yargs/yargs/commit/d585b303a43746201b05c9c9fda94a444634df33)) +* **deps:** fix enumeration for normalized path arguments ([#1567](https://www.github.com/yargs/yargs/issues/1567)) ([0b5b1b0](https://www.github.com/yargs/yargs/commit/0b5b1b0e5f4f9baf393c48e9cc2bc85c1b67a47a)) +* **locales:** only translate default option group name ([acc16de](https://www.github.com/yargs/yargs/commit/acc16de6b846ea7332db753646a9cec76b589162)) +* **locales:** remove extra space in French for 'default' ([#1564](https://www.github.com/yargs/yargs/issues/1564)) ([ecfc2c4](https://www.github.com/yargs/yargs/commit/ecfc2c474575c6cdbc6d273c94c13181bd1dbaa6)) +* **translations:** add French translation for unknown command ([#1563](https://www.github.com/yargs/yargs/issues/1563)) ([18b0b75](https://www.github.com/yargs/yargs/commit/18b0b752424bf560271e670ff95a0f90c8386787)) +* **translations:** fix pluralization in error messages. ([#1557](https://www.github.com/yargs/yargs/issues/1557)) ([94fa38c](https://www.github.com/yargs/yargs/commit/94fa38cbab8d86943e87bf41d368ed56dffa6835)) +* **yargs:** correct support of bundled electron apps ([#1554](https://www.github.com/yargs/yargs/issues/1554)) ([a0b61ac](https://www.github.com/yargs/yargs/commit/a0b61ac21e2b554aa73dbf1a66d4a7af94047c2f)) + +## [15.1.0](https://www.github.com/yargs/yargs/compare/v15.0.2...v15.1.0) (2020-01-02) + + +### Features + +* **lang:** add Finnish localization (language code fi) ([222c8fe](https://www.github.com/yargs/yargs/commit/222c8fef2e2ad46e314c337dec96940f896bec35)) +* complete short options with a single dash ([#1507](https://www.github.com/yargs/yargs/issues/1507)) ([99011ab](https://www.github.com/yargs/yargs/commit/99011ab5ba90232506ece0a17e59e2001a1ab562)) +* onFinishCommand handler ([#1473](https://www.github.com/yargs/yargs/issues/1473)) ([fe380cd](https://www.github.com/yargs/yargs/commit/fe380cd356aa33aef0449facd59c22cab8930ac9)) + + +### Bug Fixes + +* getCompletion() was not working for options ([#1495](https://www.github.com/yargs/yargs/issues/1495)) ([463feb2](https://www.github.com/yargs/yargs/commit/463feb2870158eb9df670222b0f0a40a05cf18d0)) +* misspelling of package.json `engines` field ([0891d0e](https://www.github.com/yargs/yargs/commit/0891d0ed35b30c83a6d9e9f6a5c5f84d13c546a0)) +* populate positionals when unknown-options-as-args is set ([#1508](https://www.github.com/yargs/yargs/issues/1508)) ([bb0f2eb](https://www.github.com/yargs/yargs/commit/bb0f2eb996fa4e19d330b31a01c2036cafa99a7e)), closes [#1444](https://www.github.com/yargs/yargs/issues/1444) +* show 2 dashes on help for single digit option key or alias ([#1493](https://www.github.com/yargs/yargs/issues/1493)) ([63b3dd3](https://www.github.com/yargs/yargs/commit/63b3dd31a455d428902220c1992ae930e18aff5c)) +* **docs:** use recommended cjs import syntax for ts examples ([#1513](https://www.github.com/yargs/yargs/issues/1513)) ([f9a18bf](https://www.github.com/yargs/yargs/commit/f9a18bfd624a5013108084f690cd8a1de794c430)) + +### [15.0.2](https://www.github.com/yargs/yargs/compare/v15.0.1...v15.0.2) (2019-11-19) + + +### Bug Fixes + +* temporary fix for libraries that call Object.freeze() ([#1483](https://www.github.com/yargs/yargs/issues/1483)) ([99c2dc8](https://www.github.com/yargs/yargs/commit/99c2dc850e67c606644f8b0c0bca1a59c87dcbcd)) + +### [15.0.1](https://www.github.com/yargs/yargs/compare/v15.0.0...v15.0.1) (2019-11-16) + + +### Bug Fixes + +* **deps:** cliui, find-up, and string-width, all drop Node 6 support ([#1479](https://www.github.com/yargs/yargs/issues/1479)) ([6a9ebe2](https://www.github.com/yargs/yargs/commit/6a9ebe2d955e3e979e76c07ffbb1c17fef64cb49)) + +## [15.0.0](https://www.github.com/yargs/yargs/compare/v14.2.0...v15.0.0) (2019-11-10) + + +### ⚠ BREAKING CHANGES + +* **deps:** yargs-parser now throws on invalid combinations of config (#1470) +* yargs-parser@16.0.0 drops support for Node 6 +* drop Node 6 support (#1461) +* remove package.json-based parserConfiguration (#1460) + +### Features + +* **deps:** yargs-parser now throws on invalid combinations of config ([#1470](https://www.github.com/yargs/yargs/issues/1470)) ([c10c38c](https://www.github.com/yargs/yargs/commit/c10c38cca04298f96b55a7e374a9a134abefffa7)) +* expose `Parser` from `require('yargs/yargs')` ([#1477](https://www.github.com/yargs/yargs/issues/1477)) ([1840ba2](https://www.github.com/yargs/yargs/commit/1840ba22f1a24c0ece8e32bbd31db4134a080aee)) + + +### Bug Fixes + +* **docs:** TypeScript import to prevent a future major release warning ([#1441](https://www.github.com/yargs/yargs/issues/1441)) ([b1b156a](https://www.github.com/yargs/yargs/commit/b1b156a3eb4ddd6803fbbd56c611a77919293000)) +* stop-parse was not being respected by commands ([#1459](https://www.github.com/yargs/yargs/issues/1459)) ([12c82e6](https://www.github.com/yargs/yargs/commit/12c82e62663e928148a7ee2f51629aa26a0f9bb2)) +* update to yargs-parser with fix for array default values ([#1463](https://www.github.com/yargs/yargs/issues/1463)) ([ebee59d](https://www.github.com/yargs/yargs/commit/ebee59d9022da538410e69a5c025019ed46d13d2)) +* **docs:** update boolean description and examples in docs ([#1474](https://www.github.com/yargs/yargs/issues/1474)) ([afd5b48](https://www.github.com/yargs/yargs/commit/afd5b4871bfeb90d58351ac56c5c44a83ef033e6)) + + +### Miscellaneous Chores + +* drop Node 6 support ([#1461](https://www.github.com/yargs/yargs/issues/1461)) ([2ba8ce0](https://www.github.com/yargs/yargs/commit/2ba8ce05e8fefbeffc6cb7488d9ebf6e86cceb1d)) + + +### Code Refactoring + +* remove package.json-based parserConfiguration ([#1460](https://www.github.com/yargs/yargs/issues/1460)) ([0d3642b](https://www.github.com/yargs/yargs/commit/0d3642b6f829b637938774c0c6ce5f6bfe1afa51)) + +## [14.2.0](https://github.com/yargs/yargs/compare/v14.1.0...v14.2.0) (2019-10-07) + + +### Bug Fixes + +* async middleware was called twice ([#1422](https://github.com/yargs/yargs/issues/1422)) ([9a42b63](https://github.com/yargs/yargs/commit/9a42b63)) +* fix promise check to accept any spec conform object ([#1424](https://github.com/yargs/yargs/issues/1424)) ([0be43d2](https://github.com/yargs/yargs/commit/0be43d2)) +* groups were not being maintained for nested commands ([#1430](https://github.com/yargs/yargs/issues/1430)) ([d38650e](https://github.com/yargs/yargs/commit/d38650e)) +* **docs:** broken markdown link ([#1426](https://github.com/yargs/yargs/issues/1426)) ([236e24e](https://github.com/yargs/yargs/commit/236e24e)) +* support merging deeply nested configuration ([#1423](https://github.com/yargs/yargs/issues/1423)) ([bae66fe](https://github.com/yargs/yargs/commit/bae66fe)) + + +### Features + +* **deps:** introduce yargs-parser with support for unknown-options-as-args ([#1440](https://github.com/yargs/yargs/issues/1440)) ([4d21520](https://github.com/yargs/yargs/commit/4d21520)) + +## [14.1.0](https://github.com/yargs/yargs/compare/v14.0.0...v14.1.0) (2019-09-06) + + +### Bug Fixes + +* **docs:** fix incorrect parserConfiguration documentation ([2a99124](https://github.com/yargs/yargs/commit/2a99124)) +* detect zsh when zsh isnt run as a login prompt ([#1395](https://github.com/yargs/yargs/issues/1395)) ([8792d13](https://github.com/yargs/yargs/commit/8792d13)) +* populate correct value on yargs.parsed and stop warning on access ([#1412](https://github.com/yargs/yargs/issues/1412)) ([bb0eb52](https://github.com/yargs/yargs/commit/bb0eb52)) +* showCompletionScript was logging script twice ([#1388](https://github.com/yargs/yargs/issues/1388)) ([07c8537](https://github.com/yargs/yargs/commit/07c8537)) +* strict() should not ignore hyphenated arguments ([#1414](https://github.com/yargs/yargs/issues/1414)) ([b774b5e](https://github.com/yargs/yargs/commit/b774b5e)) +* **docs:** formalize existing callback argument to showHelp ([#1386](https://github.com/yargs/yargs/issues/1386)) ([d217764](https://github.com/yargs/yargs/commit/d217764)) + + +### Features + +* make it possible to merge configurations when extending other config. ([#1411](https://github.com/yargs/yargs/issues/1411)) ([5d7ad98](https://github.com/yargs/yargs/commit/5d7ad98)) + +## [14.0.0](https://github.com/yargs/yargs/compare/v13.3.0...v14.0.0) (2019-07-30) + + +### ⚠ BREAKING CHANGES + +* we now only officially support yargs.$0 parameter and discourage direct access to yargs.parsed +* previously to this fix methods like `yargs.getOptions()` contained the state of the last command to execute. +* do not allow additional positionals in strict mode + +### Bug Fixes + +* calling parse multiple times now appropriately maintains state ([#1137](https://github.com/yargs/yargs/issues/1137)) ([#1369](https://github.com/yargs/yargs/issues/1369)) ([026b151](https://github.com/yargs/yargs/commit/026b151)) +* prefer user supplied script name in usage ([#1383](https://github.com/yargs/yargs/issues/1383)) ([28c74b9](https://github.com/yargs/yargs/commit/28c74b9)) +* **deps:** use decamelize from npm instead of vendored copy ([#1377](https://github.com/yargs/yargs/issues/1377)) ([015eeb9](https://github.com/yargs/yargs/commit/015eeb9)) +* **examples:** fix usage-options.js to reflect current API ([#1375](https://github.com/yargs/yargs/issues/1375)) ([6e5b76b](https://github.com/yargs/yargs/commit/6e5b76b)) +* do not allow additional positionals in strict mode ([35d777c](https://github.com/yargs/yargs/commit/35d777c)) +* properties accessed on singleton now reflect current state of instance ([#1366](https://github.com/yargs/yargs/issues/1366)) ([409d35b](https://github.com/yargs/yargs/commit/409d35b)) +* tolerate null prototype for config objects with `extends` ([#1376](https://github.com/yargs/yargs/issues/1376)) ([3d26d11](https://github.com/yargs/yargs/commit/3d26d11)), closes [#1372](https://github.com/yargs/yargs/issues/1372) +* yargs.parsed now populated before returning, when yargs.parse() called with no args (#1382) ([e3981fd](https://github.com/yargs/yargs/commit/e3981fd)), closes [#1382](https://github.com/yargs/yargs/issues/1382) + +### Features + +* adds support for multiple epilog messages ([#1384](https://github.com/yargs/yargs/issues/1384)) ([07a5554](https://github.com/yargs/yargs/commit/07a5554)) +* allow completionCommand to be set via showCompletionScript ([#1385](https://github.com/yargs/yargs/issues/1385)) ([5562853](https://github.com/yargs/yargs/commit/5562853)) + +## [13.3.0](https://www.github.com/yargs/yargs/compare/v13.2.4...v13.3.0) (2019-06-10) + + +### Bug Fixes + +* **deps:** yargs-parser update addressing several parsing bugs ([#1357](https://www.github.com/yargs/yargs/issues/1357)) ([e230d5b](https://www.github.com/yargs/yargs/commit/e230d5b)) + + +### Features + +* **i18n:** swap out os-locale dependency for simple inline implementation ([#1356](https://www.github.com/yargs/yargs/issues/1356)) ([4dfa19b](https://www.github.com/yargs/yargs/commit/4dfa19b)) +* support defaultDescription for positional arguments ([812048c](https://www.github.com/yargs/yargs/commit/812048c)) + +### [13.2.4](https://github.com/yargs/yargs/compare/v13.2.3...v13.2.4) (2019-05-13) + + +### Bug Fixes + +* **i18n:** rename unclear 'implication failed' to 'missing dependent arguments' ([#1317](https://github.com/yargs/yargs/issues/1317)) ([bf46813](https://github.com/yargs/yargs/commit/bf46813)) + + + +### [13.2.3](https://github.com/yargs/yargs/compare/v13.2.2...v13.2.3) (2019-05-05) + + +### Bug Fixes + +* **deps:** upgrade cliui for compatibility with latest chalk. ([#1330](https://github.com/yargs/yargs/issues/1330)) ([b20db65](https://github.com/yargs/yargs/commit/b20db65)) +* address issues with dutch translation ([#1316](https://github.com/yargs/yargs/issues/1316)) ([0295132](https://github.com/yargs/yargs/commit/0295132)) + + +### Tests + +* accept differently formatted output ([#1327](https://github.com/yargs/yargs/issues/1327)) ([c294d1b](https://github.com/yargs/yargs/commit/c294d1b)) + + + +## [13.2.2](https://github.com/yargs/yargs/compare/v13.2.1...v13.2.2) (2019-03-06) + + + +## [13.2.1](https://github.com/yargs/yargs/compare/v13.2.0...v13.2.1) (2019-02-18) + + +### Bug Fixes + +* add zsh script to files array ([3180224](https://github.com/yargs/yargs/commit/3180224)) +* support options/sub-commands in zsh completion ([0a96394](https://github.com/yargs/yargs/commit/0a96394)) + + +# [13.2.0](https://github.com/yargs/yargs/compare/v13.1.0...v13.2.0) (2019-02-15) + + +### Features + +* zsh auto completion ([#1292](https://github.com/yargs/yargs/issues/1292)) ([16c5d25](https://github.com/yargs/yargs/commit/16c5d25)), closes [#1156](https://github.com/yargs/yargs/issues/1156) + + + +# [13.1.0](https://github.com/yargs/yargs/compare/v13.0.0...v13.1.0) (2019-02-12) + + +### Features + +* add applyBeforeValidation, for applying sync middleware before validation ([5be206a](https://github.com/yargs/yargs/commit/5be206a)) + + + + +# [13.0.0](https://github.com/yargs/yargs/compare/v12.0.5...v13.0.0) (2019-02-02) + + +### Bug Fixes + +* **deps:** Update os-locale to avoid security vulnerability ([#1270](https://github.com/yargs/yargs/issues/1270)) ([27bf739](https://github.com/yargs/yargs/commit/27bf739)) +* **validation:** Use the error as a message when none exists otherwise ([#1268](https://github.com/yargs/yargs/issues/1268)) ([0510fe6](https://github.com/yargs/yargs/commit/0510fe6)) +* better bash path completion ([#1272](https://github.com/yargs/yargs/issues/1272)) ([da75ea2](https://github.com/yargs/yargs/commit/da75ea2)) +* middleware added multiple times due to reference bug ([#1282](https://github.com/yargs/yargs/issues/1282)) ([64af518](https://github.com/yargs/yargs/commit/64af518)) + + +### Chores + +* ~drop Node 6 from testing matrix ([#1287](https://github.com/yargs/yargs/issues/1287)) ([ef16792](https://github.com/yargs/yargs/commit/ef16792))~ + * _opting to not drop Node 6 support until April, [see](https://github.com/nodejs/Release)._ +* update dependencies ([#1284](https://github.com/yargs/yargs/issues/1284)) ([f25de4f](https://github.com/yargs/yargs/commit/f25de4f)) + + +### Features + +* Add `.parserConfiguration()` method, deprecating package.json config ([#1262](https://github.com/yargs/yargs/issues/1262)) ([3c6869a](https://github.com/yargs/yargs/commit/3c6869a)) +* adds config option for sorting command output ([#1256](https://github.com/yargs/yargs/issues/1256)) ([6916ce9](https://github.com/yargs/yargs/commit/6916ce9)) +* options/positionals with leading '+' and '0' no longer parse as numbers ([#1286](https://github.com/yargs/yargs/issues/1286)) ([e9dc3aa](https://github.com/yargs/yargs/commit/e9dc3aa)) +* support promises in middleware ([f3a4e4f](https://github.com/yargs/yargs/commit/f3a4e4f)) + + +### BREAKING CHANGES + +* options with leading '+' or '0' now parse as strings +* dropping Node 6 which hits end of life in April 2019 +* see [yargs-parser@12.0.0 CHANGELOG](https://github.com/yargs/yargs-parser/blob/master/CHANGELOG.md#breaking-changes) +* we now warn if the yargs stanza package.json is used. + + + + +## [12.0.5](https://github.com/yargs/yargs/compare/v12.0.4...v12.0.5) (2018-11-19) + + +### Bug Fixes + +* allows camel-case, variadic arguments, and strict mode to be combined ([#1247](https://github.com/yargs/yargs/issues/1247)) ([eacc035](https://github.com/yargs/yargs/commit/eacc035)) + + + + +## [12.0.4](https://github.com/yargs/yargs/compare/v12.0.3...v12.0.4) (2018-11-10) + + +### Bug Fixes + +* don't load config when processing positionals ([5d0dc92](https://github.com/yargs/yargs/commit/5d0dc92)) + + + + +## [12.0.3](https://github.com/yargs/yargs/compare/v12.0.2...v12.0.3) (2018-10-06) + + +### Bug Fixes + +* $0 contains first arg in bundled electron apps ([#1206](https://github.com/yargs/yargs/issues/1206)) ([567820b](https://github.com/yargs/yargs/commit/567820b)) +* accept single function for middleware ([66fd6f7](https://github.com/yargs/yargs/commit/66fd6f7)), closes [#1214](https://github.com/yargs/yargs/issues/1214) [#1214](https://github.com/yargs/yargs/issues/1214) +* hide `hidden` options from help output even if they are in a group ([#1221](https://github.com/yargs/yargs/issues/1221)) ([da54028](https://github.com/yargs/yargs/commit/da54028)) +* improve Norwegian Bokmål translations ([#1208](https://github.com/yargs/yargs/issues/1208)) ([a458fa4](https://github.com/yargs/yargs/commit/a458fa4)) +* improve Norwegian Nynorsk translations ([#1207](https://github.com/yargs/yargs/issues/1207)) ([d422eb5](https://github.com/yargs/yargs/commit/d422eb5)) + + + + +## [12.0.2](https://github.com/yargs/yargs/compare/v12.0.1...v12.0.2) (2018-09-04) + + +### Bug Fixes + +* middleware should work regardless of when method is called ([664b265](https://github.com/yargs/yargs/commit/664b265)), closes [#1178](https://github.com/yargs/yargs/issues/1178) +* translation not working when using __ with a single parameter ([#1183](https://github.com/yargs/yargs/issues/1183)) ([f449aea](https://github.com/yargs/yargs/commit/f449aea)) +* upgrade os-locale to version that addresses license issue ([#1195](https://github.com/yargs/yargs/issues/1195)) ([efc0970](https://github.com/yargs/yargs/commit/efc0970)) + + + + +## [12.0.1](https://github.com/yargs/yargs/compare/v12.0.0...v12.0.1) (2018-06-29) + + + + +# [12.0.0](https://github.com/yargs/yargs/compare/v11.1.0...v12.0.0) (2018-06-26) + + +### Bug Fixes + +* .argv and .parse() now invoke identical code path ([#1126](https://github.com/yargs/yargs/issues/1126)) ([f13ebf4](https://github.com/yargs/yargs/commit/f13ebf4)) +* remove the trailing white spaces from the help output ([#1090](https://github.com/yargs/yargs/issues/1090)) ([3f0746c](https://github.com/yargs/yargs/commit/3f0746c)) +* **completion:** Avoid default command and recommendations during completion ([#1123](https://github.com/yargs/yargs/issues/1123)) ([036e7c5](https://github.com/yargs/yargs/commit/036e7c5)) + + +### Chores + +* test Node.js 6, 8 and 10 ([#1160](https://github.com/yargs/yargs/issues/1160)) ([84f9d2b](https://github.com/yargs/yargs/commit/84f9d2b)) +* upgrade to version of yargs-parser that does not populate value for unset boolean ([#1104](https://github.com/yargs/yargs/issues/1104)) ([d4705f4](https://github.com/yargs/yargs/commit/d4705f4)) + + +### Features + +* add support for global middleware, useful for shared tasks like metrics ([#1119](https://github.com/yargs/yargs/issues/1119)) ([9d71ac7](https://github.com/yargs/yargs/commit/9d71ac7)) +* allow setting scriptName $0 ([#1143](https://github.com/yargs/yargs/issues/1143)) ([a2f2eae](https://github.com/yargs/yargs/commit/a2f2eae)) +* remove `setPlaceholderKeys` ([#1105](https://github.com/yargs/yargs/issues/1105)) ([6ee2c82](https://github.com/yargs/yargs/commit/6ee2c82)) + + +### BREAKING CHANGES + +* Options absent from `argv` (not set via CLI argument) are now absent from the parsed result object rather than being set with `undefined` +* drop Node 4 from testing matrix, such that we'll gradually start drifting away from supporting Node 4. +* yargs-parser does not populate 'false' when boolean flag is not passed +* tests that assert against help output will need to be updated + + + + +# [11.1.0](https://github.com/yargs/yargs/compare/v11.0.0...v11.1.0) (2018-03-04) + + +### Bug Fixes + +* choose correct config directory when require.main does not exist ([#1056](https://github.com/yargs/yargs/issues/1056)) ([a04678c](https://github.com/yargs/yargs/commit/a04678c)) + + +### Features + +* allow hidden options to be displayed with --show-hidden ([#1061](https://github.com/yargs/yargs/issues/1061)) ([ea862ae](https://github.com/yargs/yargs/commit/ea862ae)) +* extend *.rc files in addition to json ([#1080](https://github.com/yargs/yargs/issues/1080)) ([11691a6](https://github.com/yargs/yargs/commit/11691a6)) + + + + +# [11.0.0](https://github.com/yargs/yargs/compare/v10.1.2...v11.0.0) (2018-01-22) + + +### Bug Fixes + +* Set implicit nargs=1 when type=number requiresArg=true ([#1050](https://github.com/yargs/yargs/issues/1050)) ([2b56812](https://github.com/yargs/yargs/commit/2b56812)) + + +### Features + +* requiresArg is now simply an alias for nargs(1) ([#1054](https://github.com/yargs/yargs/issues/1054)) ([a3ddacc](https://github.com/yargs/yargs/commit/a3ddacc)) + + +### BREAKING CHANGES + +* requiresArg now has significantly different error output, matching nargs. + +[Historical Versions](/docs/CHANGELOG-historical.md) diff --git a/node_modules/yargs/LICENSE b/node_modules/yargs/LICENSE new file mode 100644 index 0000000..b0145ca --- /dev/null +++ b/node_modules/yargs/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright 2010 James Halliday (mail@substack.net); Modified work Copyright 2014 Contributors (ben@npmjs.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/yargs/README.md b/node_modules/yargs/README.md new file mode 100644 index 0000000..0db992b --- /dev/null +++ b/node_modules/yargs/README.md @@ -0,0 +1,140 @@ +

+ +

+

Yargs

+

+ Yargs be a node.js library fer hearties tryin' ter parse optstrings +

+ +
+ +[![Build Status][travis-image]][travis-url] +[![NPM version][npm-image]][npm-url] +[![js-standard-style][standard-image]][standard-url] +[![Coverage][coverage-image]][coverage-url] +[![Conventional Commits][conventional-commits-image]][conventional-commits-url] +[![Slack][slack-image]][slack-url] + +## Description : +Yargs helps you build interactive command line tools, by parsing arguments and generating an elegant user interface. + +It gives you: + +* commands and (grouped) options (`my-program.js serve --port=5000`). +* a dynamically generated help menu based on your arguments. + +> + +* bash-completion shortcuts for commands and options. +* and [tons more](/docs/api.md). + +## Installation + +Stable version: +```bash +npm i yargs +``` + +Bleeding edge version with the most recent features: +```bash +npm i yargs@next +``` + +## Usage : + +### Simple Example + +```javascript +#!/usr/bin/env node +const {argv} = require('yargs') + +if (argv.ships > 3 && argv.distance < 53.5) { + console.log('Plunder more riffiwobbles!') +} else { + console.log('Retreat from the xupptumblers!') +} +``` + +```bash +$ ./plunder.js --ships=4 --distance=22 +Plunder more riffiwobbles! + +$ ./plunder.js --ships 12 --distance 98.7 +Retreat from the xupptumblers! +``` + +### Complex Example + +```javascript +#!/usr/bin/env node +require('yargs') // eslint-disable-line + .command('serve [port]', 'start the server', (yargs) => { + yargs + .positional('port', { + describe: 'port to bind on', + default: 5000 + }) + }, (argv) => { + if (argv.verbose) console.info(`start server on :${argv.port}`) + serve(argv.port) + }) + .option('verbose', { + alias: 'v', + type: 'boolean', + description: 'Run with verbose logging' + }) + .argv +``` + +Run the example above with `--help` to see the help for the application. + +## TypeScript + +yargs has type definitions at [@types/yargs][type-definitions]. + +``` +npm i @types/yargs --save-dev +``` + +See usage examples in [docs](/docs/typescript.md). + +## Webpack + +See usage examples of yargs with webpack in [docs](/docs/webpack.md). + +## Community : + +Having problems? want to contribute? join our [community slack](http://devtoolscommunity.herokuapp.com). + +## Documentation : + +### Table of Contents + +* [Yargs' API](/docs/api.md) +* [Examples](/docs/examples.md) +* [Parsing Tricks](/docs/tricks.md) + * [Stop the Parser](/docs/tricks.md#stop) + * [Negating Boolean Arguments](/docs/tricks.md#negate) + * [Numbers](/docs/tricks.md#numbers) + * [Arrays](/docs/tricks.md#arrays) + * [Objects](/docs/tricks.md#objects) + * [Quotes](/docs/tricks.md#quotes) +* [Advanced Topics](/docs/advanced.md) + * [Composing Your App Using Commands](/docs/advanced.md#commands) + * [Building Configurable CLI Apps](/docs/advanced.md#configuration) + * [Customizing Yargs' Parser](/docs/advanced.md#customizing) +* [Contributing](/contributing.md) + +[travis-url]: https://travis-ci.org/yargs/yargs +[travis-image]: https://img.shields.io/travis/yargs/yargs/master.svg +[npm-url]: https://www.npmjs.com/package/yargs +[npm-image]: https://img.shields.io/npm/v/yargs.svg +[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg +[standard-url]: http://standardjs.com/ +[conventional-commits-image]: https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg +[conventional-commits-url]: https://conventionalcommits.org/ +[slack-image]: http://devtoolscommunity.herokuapp.com/badge.svg +[slack-url]: http://devtoolscommunity.herokuapp.com +[type-definitions]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/yargs +[coverage-image]: https://img.shields.io/nycrc/yargs/yargs +[coverage-url]: https://github.com/yargs/yargs/blob/master/.nycrc diff --git a/node_modules/yargs/build/lib/apply-extends.d.ts b/node_modules/yargs/build/lib/apply-extends.d.ts new file mode 100644 index 0000000..5a9aca7 --- /dev/null +++ b/node_modules/yargs/build/lib/apply-extends.d.ts @@ -0,0 +1,2 @@ +import { Dictionary } from './common-types'; +export declare function applyExtends(config: Dictionary, cwd: string, mergeExtends?: boolean): Dictionary; diff --git a/node_modules/yargs/build/lib/apply-extends.js b/node_modules/yargs/build/lib/apply-extends.js new file mode 100644 index 0000000..005734a --- /dev/null +++ b/node_modules/yargs/build/lib/apply-extends.js @@ -0,0 +1,65 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.applyExtends = void 0; +const fs = require("fs"); +const path = require("path"); +const yerror_1 = require("./yerror"); +let previouslyVisitedConfigs = []; +function checkForCircularExtends(cfgPath) { + if (previouslyVisitedConfigs.indexOf(cfgPath) > -1) { + throw new yerror_1.YError(`Circular extended configurations: '${cfgPath}'.`); + } +} +function getPathToDefaultConfig(cwd, pathToExtend) { + return path.resolve(cwd, pathToExtend); +} +function mergeDeep(config1, config2) { + const target = {}; + function isObject(obj) { + return obj && typeof obj === 'object' && !Array.isArray(obj); + } + Object.assign(target, config1); + for (const key of Object.keys(config2)) { + if (isObject(config2[key]) && isObject(target[key])) { + target[key] = mergeDeep(config1[key], config2[key]); + } + else { + target[key] = config2[key]; + } + } + return target; +} +function applyExtends(config, cwd, mergeExtends = false) { + let defaultConfig = {}; + if (Object.prototype.hasOwnProperty.call(config, 'extends')) { + if (typeof config.extends !== 'string') + return defaultConfig; + const isPath = /\.json|\..*rc$/.test(config.extends); + let pathToDefault = null; + if (!isPath) { + try { + pathToDefault = require.resolve(config.extends); + } + catch (err) { + // most likely this simply isn't a module. + } + } + else { + pathToDefault = getPathToDefaultConfig(cwd, config.extends); + } + // maybe the module uses key for some other reason, + // err on side of caution. + if (!pathToDefault && !isPath) + return config; + if (!pathToDefault) + throw new yerror_1.YError(`Unable to find extended config '${config.extends}' in '${cwd}'.`); + checkForCircularExtends(pathToDefault); + previouslyVisitedConfigs.push(pathToDefault); + defaultConfig = isPath ? JSON.parse(fs.readFileSync(pathToDefault, 'utf8')) : require(config.extends); + delete config.extends; + defaultConfig = applyExtends(defaultConfig, path.dirname(pathToDefault), mergeExtends); + } + previouslyVisitedConfigs = []; + return mergeExtends ? mergeDeep(defaultConfig, config) : Object.assign({}, defaultConfig, config); +} +exports.applyExtends = applyExtends; diff --git a/node_modules/yargs/build/lib/argsert.d.ts b/node_modules/yargs/build/lib/argsert.d.ts new file mode 100644 index 0000000..6f7a83f --- /dev/null +++ b/node_modules/yargs/build/lib/argsert.d.ts @@ -0,0 +1,2 @@ +export declare function argsert(callerArguments: any[], length?: number): void; +export declare function argsert(expected: string, callerArguments: any[], length?: number): void; diff --git a/node_modules/yargs/build/lib/argsert.js b/node_modules/yargs/build/lib/argsert.js new file mode 100644 index 0000000..40cb091 --- /dev/null +++ b/node_modules/yargs/build/lib/argsert.js @@ -0,0 +1,65 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.argsert = void 0; +const yerror_1 = require("./yerror"); +const parse_command_1 = require("./parse-command"); +const positionName = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']; +function argsert(arg1, arg2, arg3) { + function parseArgs() { + return typeof arg1 === 'object' + ? [{ demanded: [], optional: [] }, arg1, arg2] + : [parse_command_1.parseCommand(`cmd ${arg1}`), arg2, arg3]; + } + // TODO: should this eventually raise an exception. + try { + // preface the argument description with "cmd", so + // that we can run it through yargs' command parser. + let position = 0; + let [parsed, callerArguments, length] = parseArgs(); + const args = [].slice.call(callerArguments); + while (args.length && args[args.length - 1] === undefined) + args.pop(); + length = length || args.length; + if (length < parsed.demanded.length) { + throw new yerror_1.YError(`Not enough arguments provided. Expected ${parsed.demanded.length} but received ${args.length}.`); + } + const totalCommands = parsed.demanded.length + parsed.optional.length; + if (length > totalCommands) { + throw new yerror_1.YError(`Too many arguments provided. Expected max ${totalCommands} but received ${length}.`); + } + parsed.demanded.forEach((demanded) => { + const arg = args.shift(); + const observedType = guessType(arg); + const matchingTypes = demanded.cmd.filter(type => type === observedType || type === '*'); + if (matchingTypes.length === 0) + argumentTypeError(observedType, demanded.cmd, position); + position += 1; + }); + parsed.optional.forEach((optional) => { + if (args.length === 0) + return; + const arg = args.shift(); + const observedType = guessType(arg); + const matchingTypes = optional.cmd.filter(type => type === observedType || type === '*'); + if (matchingTypes.length === 0) + argumentTypeError(observedType, optional.cmd, position); + position += 1; + }); + } + catch (err) { + console.warn(err.stack); + } +} +exports.argsert = argsert; +function guessType(arg) { + if (Array.isArray(arg)) { + return 'array'; + } + else if (arg === null) { + return 'null'; + } + return typeof arg; +} +function argumentTypeError(observedType, allowedTypes, position) { + throw new yerror_1.YError(`Invalid ${positionName[position] || 'manyith'} argument. Expected ${allowedTypes.join(' or ')} but received ${observedType}.`); +} diff --git a/node_modules/yargs/build/lib/command.d.ts b/node_modules/yargs/build/lib/command.d.ts new file mode 100644 index 0000000..9db6ab5 --- /dev/null +++ b/node_modules/yargs/build/lib/command.d.ts @@ -0,0 +1,64 @@ +/// +import { Dictionary } from './common-types'; +import { Middleware } from './middleware'; +import { Positional } from './parse-command'; +import { RequireDirectoryOptions } from 'require-directory'; +import { UsageInstance } from './usage'; +import { ValidationInstance } from './validation'; +import { YargsInstance, Options, OptionDefinition, Context, Arguments, DetailedArguments } from './yargs'; +export declare function command(yargs: YargsInstance, usage: UsageInstance, validation: ValidationInstance, globalMiddleware?: Middleware[]): CommandInstance; +/** Instance of the command module. */ +export interface CommandInstance { + addDirectory(dir: string, context: Context, req: NodeRequireFunction, callerFile: string, opts?: RequireDirectoryOptions): void; + addHandler(handler: CommandHandlerDefinition): void; + addHandler(cmd: string | string[], description: CommandHandler['description'], builder?: CommandBuilderDefinition | CommandBuilder, handler?: CommandHandlerCallback, commandMiddleware?: Middleware[], deprecated?: boolean): void; + cmdToParseOptions(cmdString: string): Positionals; + freeze(): void; + getCommandHandlers(): Dictionary; + getCommands(): string[]; + hasDefaultCommand(): boolean; + reset(): CommandInstance; + runCommand(command: string | null, yargs: YargsInstance, parsed: DetailedArguments, commandIndex?: number): Arguments | Promise; + runDefaultBuilderOn(yargs: YargsInstance): void; + unfreeze(): void; +} +export interface CommandHandlerDefinition extends Partial> { + aliases?: string[]; + builder?: CommandBuilder | CommandBuilderDefinition; + command?: string | string[]; + desc?: CommandHandler['description']; + describe?: CommandHandler['description']; +} +export declare function isCommandHandlerDefinition(cmd: string | string[] | CommandHandlerDefinition): cmd is CommandHandlerDefinition; +export interface CommandBuilderDefinition { + builder?: CommandBuilder; + deprecated?: boolean; + handler: CommandHandlerCallback; + middlewares?: Middleware[]; +} +export declare function isCommandBuilderDefinition(builder?: CommandBuilder | CommandBuilderDefinition): builder is CommandBuilderDefinition; +export interface CommandHandlerCallback { + (argv: Arguments): any; +} +export interface CommandHandler { + builder: CommandBuilder; + demanded: Positional[]; + deprecated?: boolean; + description?: string | false; + handler: CommandHandlerCallback; + middlewares: Middleware[]; + optional: Positional[]; + original: string; +} +export declare type CommandBuilder = CommandBuilderCallback | Dictionary; +interface CommandBuilderCallback { + (y: YargsInstance): YargsInstance | void; +} +export declare function isCommandBuilderCallback(builder: CommandBuilder): builder is CommandBuilderCallback; +interface Positionals extends Pick { + demand: Dictionary; +} +export interface FinishCommandHandler { + (handlerResult: any): any; +} +export {}; diff --git a/node_modules/yargs/build/lib/command.js b/node_modules/yargs/build/lib/command.js new file mode 100644 index 0000000..d90c455 --- /dev/null +++ b/node_modules/yargs/build/lib/command.js @@ -0,0 +1,416 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isCommandBuilderCallback = exports.isCommandBuilderDefinition = exports.isCommandHandlerDefinition = exports.command = void 0; +const common_types_1 = require("./common-types"); +const is_promise_1 = require("./is-promise"); +const middleware_1 = require("./middleware"); +const parse_command_1 = require("./parse-command"); +const path = require("path"); +const util_1 = require("util"); +const yargs_1 = require("./yargs"); +const requireDirectory = require("require-directory"); +const whichModule = require("which-module"); +const Parser = require("yargs-parser"); +const DEFAULT_MARKER = /(^\*)|(^\$0)/; +// handles parsing positional arguments, +// and populating argv with said positional +// arguments. +function command(yargs, usage, validation, globalMiddleware = []) { + const self = {}; + let handlers = {}; + let aliasMap = {}; + let defaultCommand; + self.addHandler = function addHandler(cmd, description, builder, handler, commandMiddleware, deprecated) { + let aliases = []; + const middlewares = middleware_1.commandMiddlewareFactory(commandMiddleware); + handler = handler || (() => { }); + if (Array.isArray(cmd)) { + aliases = cmd.slice(1); + cmd = cmd[0]; + } + else if (isCommandHandlerDefinition(cmd)) { + let command = (Array.isArray(cmd.command) || typeof cmd.command === 'string') ? cmd.command : moduleName(cmd); + if (cmd.aliases) + command = [].concat(command).concat(cmd.aliases); + self.addHandler(command, extractDesc(cmd), cmd.builder, cmd.handler, cmd.middlewares, cmd.deprecated); + return; + } + // allow a module to be provided instead of separate builder and handler + if (isCommandBuilderDefinition(builder)) { + self.addHandler([cmd].concat(aliases), description, builder.builder, builder.handler, builder.middlewares, builder.deprecated); + return; + } + // parse positionals out of cmd string + const parsedCommand = parse_command_1.parseCommand(cmd); + // remove positional args from aliases only + aliases = aliases.map(alias => parse_command_1.parseCommand(alias).cmd); + // check for default and filter out '*'' + let isDefault = false; + const parsedAliases = [parsedCommand.cmd].concat(aliases).filter((c) => { + if (DEFAULT_MARKER.test(c)) { + isDefault = true; + return false; + } + return true; + }); + // standardize on $0 for default command. + if (parsedAliases.length === 0 && isDefault) + parsedAliases.push('$0'); + // shift cmd and aliases after filtering out '*' + if (isDefault) { + parsedCommand.cmd = parsedAliases[0]; + aliases = parsedAliases.slice(1); + cmd = cmd.replace(DEFAULT_MARKER, parsedCommand.cmd); + } + // populate aliasMap + aliases.forEach((alias) => { + aliasMap[alias] = parsedCommand.cmd; + }); + if (description !== false) { + usage.command(cmd, description, isDefault, aliases, deprecated); + } + handlers[parsedCommand.cmd] = { + original: cmd, + description, + handler, + builder: builder || {}, + middlewares, + deprecated, + demanded: parsedCommand.demanded, + optional: parsedCommand.optional + }; + if (isDefault) + defaultCommand = handlers[parsedCommand.cmd]; + }; + self.addDirectory = function addDirectory(dir, context, req, callerFile, opts) { + opts = opts || {}; + // disable recursion to support nested directories of subcommands + if (typeof opts.recurse !== 'boolean') + opts.recurse = false; + // exclude 'json', 'coffee' from require-directory defaults + if (!Array.isArray(opts.extensions)) + opts.extensions = ['js']; + // allow consumer to define their own visitor function + const parentVisit = typeof opts.visit === 'function' ? opts.visit : (o) => o; + // call addHandler via visitor function + opts.visit = function visit(obj, joined, filename) { + const visited = parentVisit(obj, joined, filename); + // allow consumer to skip modules with their own visitor + if (visited) { + // check for cyclic reference + // each command file path should only be seen once per execution + if (~context.files.indexOf(joined)) + return visited; + // keep track of visited files in context.files + context.files.push(joined); + self.addHandler(visited); + } + return visited; + }; + requireDirectory({ require: req, filename: callerFile }, dir, opts); + }; + // lookup module object from require()d command and derive name + // if module was not require()d and no name given, throw error + function moduleName(obj) { + const mod = whichModule(obj); + if (!mod) + throw new Error(`No command name given for module: ${util_1.inspect(obj)}`); + return commandFromFilename(mod.filename); + } + // derive command name from filename + function commandFromFilename(filename) { + return path.basename(filename, path.extname(filename)); + } + function extractDesc({ describe, description, desc }) { + for (const test of [describe, description, desc]) { + if (typeof test === 'string' || test === false) + return test; + common_types_1.assertNotStrictEqual(test, true); + } + return false; + } + self.getCommands = () => Object.keys(handlers).concat(Object.keys(aliasMap)); + self.getCommandHandlers = () => handlers; + self.hasDefaultCommand = () => !!defaultCommand; + self.runCommand = function runCommand(command, yargs, parsed, commandIndex) { + let aliases = parsed.aliases; + const commandHandler = handlers[command] || handlers[aliasMap[command]] || defaultCommand; + const currentContext = yargs.getContext(); + let numFiles = currentContext.files.length; + const parentCommands = currentContext.commands.slice(); + // what does yargs look like after the builder is run? + let innerArgv = parsed.argv; + let positionalMap = {}; + if (command) { + currentContext.commands.push(command); + currentContext.fullCommands.push(commandHandler.original); + } + const builder = commandHandler.builder; + if (isCommandBuilderCallback(builder)) { + // a function can be provided, which builds + // up a yargs chain and possibly returns it. + const builderOutput = builder(yargs.reset(parsed.aliases)); + const innerYargs = yargs_1.isYargsInstance(builderOutput) ? builderOutput : yargs; + if (shouldUpdateUsage(innerYargs)) { + innerYargs.getUsageInstance().usage(usageFromParentCommandsCommandHandler(parentCommands, commandHandler), commandHandler.description); + } + innerArgv = innerYargs._parseArgs(null, null, true, commandIndex); + aliases = innerYargs.parsed.aliases; + } + else if (isCommandBuilderOptionDefinitions(builder)) { + // as a short hand, an object can instead be provided, specifying + // the options that a command takes. + const innerYargs = yargs.reset(parsed.aliases); + if (shouldUpdateUsage(innerYargs)) { + innerYargs.getUsageInstance().usage(usageFromParentCommandsCommandHandler(parentCommands, commandHandler), commandHandler.description); + } + Object.keys(commandHandler.builder).forEach((key) => { + innerYargs.option(key, builder[key]); + }); + innerArgv = innerYargs._parseArgs(null, null, true, commandIndex); + aliases = innerYargs.parsed.aliases; + } + if (!yargs._hasOutput()) { + positionalMap = populatePositionals(commandHandler, innerArgv, currentContext); + } + const middlewares = globalMiddleware.slice(0).concat(commandHandler.middlewares); + middleware_1.applyMiddleware(innerArgv, yargs, middlewares, true); + // we apply validation post-hoc, so that custom + // checks get passed populated positional arguments. + if (!yargs._hasOutput()) { + yargs._runValidation(innerArgv, aliases, positionalMap, yargs.parsed.error, !command); + } + if (commandHandler.handler && !yargs._hasOutput()) { + yargs._setHasOutput(); + // to simplify the parsing of positionals in commands, + // we temporarily populate '--' rather than _, with arguments + const populateDoubleDash = !!yargs.getOptions().configuration['populate--']; + if (!populateDoubleDash) + yargs._copyDoubleDash(innerArgv); + innerArgv = middleware_1.applyMiddleware(innerArgv, yargs, middlewares, false); + let handlerResult; + if (is_promise_1.isPromise(innerArgv)) { + handlerResult = innerArgv.then(argv => commandHandler.handler(argv)); + } + else { + handlerResult = commandHandler.handler(innerArgv); + } + const handlerFinishCommand = yargs.getHandlerFinishCommand(); + if (is_promise_1.isPromise(handlerResult)) { + yargs.getUsageInstance().cacheHelpMessage(); + handlerResult + .then(value => { + if (handlerFinishCommand) { + handlerFinishCommand(value); + } + }) + .catch(error => { + try { + yargs.getUsageInstance().fail(null, error); + } + catch (err) { + // fail's throwing would cause an unhandled rejection. + } + }) + .then(() => { + yargs.getUsageInstance().clearCachedHelpMessage(); + }); + } + else { + if (handlerFinishCommand) { + handlerFinishCommand(handlerResult); + } + } + } + if (command) { + currentContext.commands.pop(); + currentContext.fullCommands.pop(); + } + numFiles = currentContext.files.length - numFiles; + if (numFiles > 0) + currentContext.files.splice(numFiles * -1, numFiles); + return innerArgv; + }; + function shouldUpdateUsage(yargs) { + return !yargs.getUsageInstance().getUsageDisabled() && + yargs.getUsageInstance().getUsage().length === 0; + } + function usageFromParentCommandsCommandHandler(parentCommands, commandHandler) { + const c = DEFAULT_MARKER.test(commandHandler.original) ? commandHandler.original.replace(DEFAULT_MARKER, '').trim() : commandHandler.original; + const pc = parentCommands.filter((c) => { return !DEFAULT_MARKER.test(c); }); + pc.push(c); + return `$0 ${pc.join(' ')}`; + } + self.runDefaultBuilderOn = function (yargs) { + common_types_1.assertNotStrictEqual(defaultCommand, undefined); + if (shouldUpdateUsage(yargs)) { + // build the root-level command string from the default string. + const commandString = DEFAULT_MARKER.test(defaultCommand.original) + ? defaultCommand.original : defaultCommand.original.replace(/^[^[\]<>]*/, '$0 '); + yargs.getUsageInstance().usage(commandString, defaultCommand.description); + } + const builder = defaultCommand.builder; + if (isCommandBuilderCallback(builder)) { + builder(yargs); + } + else { + Object.keys(builder).forEach((key) => { + yargs.option(key, builder[key]); + }); + } + }; + // transcribe all positional arguments "command [apple]" + // onto argv. + function populatePositionals(commandHandler, argv, context) { + argv._ = argv._.slice(context.commands.length); // nuke the current commands + const demanded = commandHandler.demanded.slice(0); + const optional = commandHandler.optional.slice(0); + const positionalMap = {}; + validation.positionalCount(demanded.length, argv._.length); + while (demanded.length) { + const demand = demanded.shift(); + populatePositional(demand, argv, positionalMap); + } + while (optional.length) { + const maybe = optional.shift(); + populatePositional(maybe, argv, positionalMap); + } + argv._ = context.commands.concat(argv._); + postProcessPositionals(argv, positionalMap, self.cmdToParseOptions(commandHandler.original)); + return positionalMap; + } + function populatePositional(positional, argv, positionalMap) { + const cmd = positional.cmd[0]; + if (positional.variadic) { + positionalMap[cmd] = argv._.splice(0).map(String); + } + else { + if (argv._.length) + positionalMap[cmd] = [String(argv._.shift())]; + } + } + // we run yargs-parser against the positional arguments + // applying the same parsing logic used for flags. + function postProcessPositionals(argv, positionalMap, parseOptions) { + // combine the parsing hints we've inferred from the command + // string with explicitly configured parsing hints. + const options = Object.assign({}, yargs.getOptions()); + options.default = Object.assign(parseOptions.default, options.default); + for (const key of Object.keys(parseOptions.alias)) { + options.alias[key] = (options.alias[key] || []).concat(parseOptions.alias[key]); + } + options.array = options.array.concat(parseOptions.array); + delete options.config; // don't load config when processing positionals. + const unparsed = []; + Object.keys(positionalMap).forEach((key) => { + positionalMap[key].map((value) => { + if (options.configuration['unknown-options-as-args']) + options.key[key] = true; + unparsed.push(`--${key}`); + unparsed.push(value); + }); + }); + // short-circuit parse. + if (!unparsed.length) + return; + const config = Object.assign({}, options.configuration, { + 'populate--': true + }); + const parsed = Parser.detailed(unparsed, Object.assign({}, options, { + configuration: config + })); + if (parsed.error) { + yargs.getUsageInstance().fail(parsed.error.message, parsed.error); + } + else { + // only copy over positional keys (don't overwrite + // flag arguments that were already parsed). + const positionalKeys = Object.keys(positionalMap); + Object.keys(positionalMap).forEach((key) => { + positionalKeys.push(...parsed.aliases[key]); + }); + Object.keys(parsed.argv).forEach((key) => { + if (positionalKeys.indexOf(key) !== -1) { + // any new aliases need to be placed in positionalMap, which + // is used for validation. + if (!positionalMap[key]) + positionalMap[key] = parsed.argv[key]; + argv[key] = parsed.argv[key]; + } + }); + } + } + self.cmdToParseOptions = function (cmdString) { + const parseOptions = { + array: [], + default: {}, + alias: {}, + demand: {} + }; + const parsed = parse_command_1.parseCommand(cmdString); + parsed.demanded.forEach((d) => { + const [cmd, ...aliases] = d.cmd; + if (d.variadic) { + parseOptions.array.push(cmd); + parseOptions.default[cmd] = []; + } + parseOptions.alias[cmd] = aliases; + parseOptions.demand[cmd] = true; + }); + parsed.optional.forEach((o) => { + const [cmd, ...aliases] = o.cmd; + if (o.variadic) { + parseOptions.array.push(cmd); + parseOptions.default[cmd] = []; + } + parseOptions.alias[cmd] = aliases; + }); + return parseOptions; + }; + self.reset = () => { + handlers = {}; + aliasMap = {}; + defaultCommand = undefined; + return self; + }; + // used by yargs.parse() to freeze + // the state of commands such that + // we can apply .parse() multiple times + // with the same yargs instance. + const frozens = []; + self.freeze = () => { + frozens.push({ + handlers, + aliasMap, + defaultCommand + }); + }; + self.unfreeze = () => { + const frozen = frozens.pop(); + common_types_1.assertNotStrictEqual(frozen, undefined); + ({ + handlers, + aliasMap, + defaultCommand + } = frozen); + }; + return self; +} +exports.command = command; +function isCommandHandlerDefinition(cmd) { + return typeof cmd === 'object'; +} +exports.isCommandHandlerDefinition = isCommandHandlerDefinition; +function isCommandBuilderDefinition(builder) { + return typeof builder === 'object' && + !!builder.builder && + typeof builder.handler === 'function'; +} +exports.isCommandBuilderDefinition = isCommandBuilderDefinition; +function isCommandBuilderCallback(builder) { + return typeof builder === 'function'; +} +exports.isCommandBuilderCallback = isCommandBuilderCallback; +function isCommandBuilderOptionDefinitions(builder) { + return typeof builder === 'object'; +} diff --git a/node_modules/yargs/build/lib/common-types.d.ts b/node_modules/yargs/build/lib/common-types.d.ts new file mode 100644 index 0000000..f83c0dd --- /dev/null +++ b/node_modules/yargs/build/lib/common-types.d.ts @@ -0,0 +1,36 @@ +/** + * An object whose all properties have the same type. + */ +export declare type Dictionary = { + [key: string]: T; +}; +/** + * Returns the keys of T that match Dictionary and are not arrays. + */ +export declare type DictionaryKeyof = Exclude>, KeyOf>; +/** + * Returns the keys of T that match U. + */ +export declare type KeyOf = Exclude<{ + [K in keyof T]: T[K] extends U ? K : never; +}[keyof T], undefined>; +/** + * An array whose first element is not undefined. + */ +export declare type NotEmptyArray = [T, ...T[]]; +/** + * Returns the type of a Dictionary or array values. + */ +export declare type ValueOf = T extends (infer U)[] ? U : T[keyof T]; +/** + * Typing wrapper around assert.notStrictEqual() + */ +export declare function assertNotStrictEqual(actual: T | N, expected: N, message?: string | Error): asserts actual is Exclude; +/** + * Asserts actual is a single key, not a key array or a key map. + */ +export declare function assertSingleKey(actual: string | string[] | Dictionary): asserts actual is string; +/** + * Typing wrapper around Object.keys() + */ +export declare function objectKeys(object: T): (keyof T)[]; diff --git a/node_modules/yargs/build/lib/common-types.js b/node_modules/yargs/build/lib/common-types.js new file mode 100644 index 0000000..3064cbf --- /dev/null +++ b/node_modules/yargs/build/lib/common-types.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.objectKeys = exports.assertSingleKey = exports.assertNotStrictEqual = void 0; +const assert_1 = require("assert"); +/** + * Typing wrapper around assert.notStrictEqual() + */ +function assertNotStrictEqual(actual, expected, message) { + assert_1.notStrictEqual(actual, expected, message); +} +exports.assertNotStrictEqual = assertNotStrictEqual; +/** + * Asserts actual is a single key, not a key array or a key map. + */ +function assertSingleKey(actual) { + assert_1.strictEqual(typeof actual, 'string'); +} +exports.assertSingleKey = assertSingleKey; +/** + * Typing wrapper around Object.keys() + */ +function objectKeys(object) { + return Object.keys(object); +} +exports.objectKeys = objectKeys; diff --git a/node_modules/yargs/build/lib/completion-templates.d.ts b/node_modules/yargs/build/lib/completion-templates.d.ts new file mode 100644 index 0000000..67bcd30 --- /dev/null +++ b/node_modules/yargs/build/lib/completion-templates.d.ts @@ -0,0 +1,2 @@ +export declare const completionShTemplate = "###-begin-{{app_name}}-completions-###\n#\n# yargs command completion script\n#\n# Installation: {{app_path}} {{completion_command}} >> ~/.bashrc\n# or {{app_path}} {{completion_command}} >> ~/.bash_profile on OSX.\n#\n_yargs_completions()\n{\n local cur_word args type_list\n\n cur_word=\"${COMP_WORDS[COMP_CWORD]}\"\n args=(\"${COMP_WORDS[@]}\")\n\n # ask yargs to generate completions.\n type_list=$({{app_path}} --get-yargs-completions \"${args[@]}\")\n\n COMPREPLY=( $(compgen -W \"${type_list}\" -- ${cur_word}) )\n\n # if no match was found, fall back to filename completion\n if [ ${#COMPREPLY[@]} -eq 0 ]; then\n COMPREPLY=()\n fi\n\n return 0\n}\ncomplete -o default -F _yargs_completions {{app_name}}\n###-end-{{app_name}}-completions-###\n"; +export declare const completionZshTemplate = "###-begin-{{app_name}}-completions-###\n#\n# yargs command completion script\n#\n# Installation: {{app_path}} {{completion_command}} >> ~/.zshrc\n# or {{app_path}} {{completion_command}} >> ~/.zsh_profile on OSX.\n#\n_{{app_name}}_yargs_completions()\n{\n local reply\n local si=$IFS\n IFS=$'\n' reply=($(COMP_CWORD=\"$((CURRENT-1))\" COMP_LINE=\"$BUFFER\" COMP_POINT=\"$CURSOR\" {{app_path}} --get-yargs-completions \"${words[@]}\"))\n IFS=$si\n _describe 'values' reply\n}\ncompdef _{{app_name}}_yargs_completions {{app_name}}\n###-end-{{app_name}}-completions-###\n"; diff --git a/node_modules/yargs/build/lib/completion-templates.js b/node_modules/yargs/build/lib/completion-templates.js new file mode 100644 index 0000000..3ee0e06 --- /dev/null +++ b/node_modules/yargs/build/lib/completion-templates.js @@ -0,0 +1,50 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.completionZshTemplate = exports.completionShTemplate = void 0; +exports.completionShTemplate = `###-begin-{{app_name}}-completions-### +# +# yargs command completion script +# +# Installation: {{app_path}} {{completion_command}} >> ~/.bashrc +# or {{app_path}} {{completion_command}} >> ~/.bash_profile on OSX. +# +_yargs_completions() +{ + local cur_word args type_list + + cur_word="\${COMP_WORDS[COMP_CWORD]}" + args=("\${COMP_WORDS[@]}") + + # ask yargs to generate completions. + type_list=$({{app_path}} --get-yargs-completions "\${args[@]}") + + COMPREPLY=( $(compgen -W "\${type_list}" -- \${cur_word}) ) + + # if no match was found, fall back to filename completion + if [ \${#COMPREPLY[@]} -eq 0 ]; then + COMPREPLY=() + fi + + return 0 +} +complete -o default -F _yargs_completions {{app_name}} +###-end-{{app_name}}-completions-### +`; +exports.completionZshTemplate = `###-begin-{{app_name}}-completions-### +# +# yargs command completion script +# +# Installation: {{app_path}} {{completion_command}} >> ~/.zshrc +# or {{app_path}} {{completion_command}} >> ~/.zsh_profile on OSX. +# +_{{app_name}}_yargs_completions() +{ + local reply + local si=$IFS + IFS=$'\n' reply=($(COMP_CWORD="$((CURRENT-1))" COMP_LINE="$BUFFER" COMP_POINT="$CURSOR" {{app_path}} --get-yargs-completions "\${words[@]}")) + IFS=$si + _describe 'values' reply +} +compdef _{{app_name}}_yargs_completions {{app_name}} +###-end-{{app_name}}-completions-### +`; diff --git a/node_modules/yargs/build/lib/completion.d.ts b/node_modules/yargs/build/lib/completion.d.ts new file mode 100644 index 0000000..176a91b --- /dev/null +++ b/node_modules/yargs/build/lib/completion.d.ts @@ -0,0 +1,21 @@ +import { CommandInstance } from './command'; +import { UsageInstance } from './usage'; +import { YargsInstance } from './yargs'; +import { Arguments, DetailedArguments } from 'yargs-parser'; +export declare function completion(yargs: YargsInstance, usage: UsageInstance, command: CommandInstance): CompletionInstance; +/** Instance of the completion module. */ +export interface CompletionInstance { + completionKey: string; + generateCompletionScript($0: string, cmd: string): string; + getCompletion(args: string[], done: (completions: string[]) => any): any; + registerFunction(fn: CompletionFunction): void; + setParsed(parsed: DetailedArguments): void; +} +export declare type CompletionFunction = SyncCompletionFunction | AsyncCompletionFunction; +interface SyncCompletionFunction { + (current: string, argv: Arguments): string[] | Promise; +} +interface AsyncCompletionFunction { + (current: string, argv: Arguments, done: (completions: string[]) => any): any; +} +export {}; diff --git a/node_modules/yargs/build/lib/completion.js b/node_modules/yargs/build/lib/completion.js new file mode 100644 index 0000000..d65925a --- /dev/null +++ b/node_modules/yargs/build/lib/completion.js @@ -0,0 +1,135 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.completion = void 0; +const command_1 = require("./command"); +const templates = require("./completion-templates"); +const is_promise_1 = require("./is-promise"); +const parse_command_1 = require("./parse-command"); +const path = require("path"); +const common_types_1 = require("./common-types"); +// add bash completions to your +// yargs-powered applications. +function completion(yargs, usage, command) { + const self = { + completionKey: 'get-yargs-completions' + }; + let aliases; + self.setParsed = function setParsed(parsed) { + aliases = parsed.aliases; + }; + const zshShell = (process.env.SHELL && process.env.SHELL.indexOf('zsh') !== -1) || + (process.env.ZSH_NAME && process.env.ZSH_NAME.indexOf('zsh') !== -1); + // get a list of completion commands. + // 'args' is the array of strings from the line to be completed + self.getCompletion = function getCompletion(args, done) { + const completions = []; + const current = args.length ? args[args.length - 1] : ''; + const argv = yargs.parse(args, true); + const parentCommands = yargs.getContext().commands; + // a custom completion function can be provided + // to completion(). + function runCompletionFunction(argv) { + common_types_1.assertNotStrictEqual(completionFunction, null); + if (isSyncCompletionFunction(completionFunction)) { + const result = completionFunction(current, argv); + // promise based completion function. + if (is_promise_1.isPromise(result)) { + return result.then((list) => { + process.nextTick(() => { done(list); }); + }).catch((err) => { + process.nextTick(() => { throw err; }); + }); + } + // synchronous completion function. + return done(result); + } + else { + // asynchronous completion function + return completionFunction(current, argv, (completions) => { + done(completions); + }); + } + } + if (completionFunction) { + return is_promise_1.isPromise(argv) ? argv.then(runCompletionFunction) : runCompletionFunction(argv); + } + const handlers = command.getCommandHandlers(); + for (let i = 0, ii = args.length; i < ii; ++i) { + if (handlers[args[i]] && handlers[args[i]].builder) { + const builder = handlers[args[i]].builder; + if (command_1.isCommandBuilderCallback(builder)) { + const y = yargs.reset(); + builder(y); + return y.argv; + } + } + } + if (!current.match(/^-/) && parentCommands[parentCommands.length - 1] !== current) { + usage.getCommands().forEach((usageCommand) => { + const commandName = parse_command_1.parseCommand(usageCommand[0]).cmd; + if (args.indexOf(commandName) === -1) { + if (!zshShell) { + completions.push(commandName); + } + else { + const desc = usageCommand[1] || ''; + completions.push(commandName.replace(/:/g, '\\:') + ':' + desc); + } + } + }); + } + if (current.match(/^-/) || (current === '' && completions.length === 0)) { + const descs = usage.getDescriptions(); + const options = yargs.getOptions(); + Object.keys(options.key).forEach((key) => { + const negable = !!options.configuration['boolean-negation'] && options.boolean.includes(key); + // If the key and its aliases aren't in 'args', add the key to 'completions' + let keyAndAliases = [key].concat(aliases[key] || []); + if (negable) + keyAndAliases = keyAndAliases.concat(keyAndAliases.map(key => `no-${key}`)); + function completeOptionKey(key) { + const notInArgs = keyAndAliases.every(val => args.indexOf(`--${val}`) === -1); + if (notInArgs) { + const startsByTwoDashes = (s) => /^--/.test(s); + const isShortOption = (s) => /^[^0-9]$/.test(s); + const dashes = !startsByTwoDashes(current) && isShortOption(key) ? '-' : '--'; + if (!zshShell) { + completions.push(dashes + key); + } + else { + const desc = descs[key] || ''; + completions.push(dashes + `${key.replace(/:/g, '\\:')}:${desc.replace('__yargsString__:', '')}`); + } + } + } + completeOptionKey(key); + if (negable && !!options.default[key]) + completeOptionKey(`no-${key}`); + }); + } + done(completions); + }; + // generate the completion script to add to your .bashrc. + self.generateCompletionScript = function generateCompletionScript($0, cmd) { + let script = zshShell ? templates.completionZshTemplate : templates.completionShTemplate; + const name = path.basename($0); + // add ./to applications not yet installed as bin. + if ($0.match(/\.js$/)) + $0 = `./${$0}`; + script = script.replace(/{{app_name}}/g, name); + script = script.replace(/{{completion_command}}/g, cmd); + return script.replace(/{{app_path}}/g, $0); + }; + // register a function to perform your own custom + // completions., this function can be either + // synchrnous or asynchronous. + let completionFunction = null; + self.registerFunction = (fn) => { + completionFunction = fn; + }; + return self; +} +exports.completion = completion; +function isSyncCompletionFunction(completionFunction) { + return completionFunction.length < 3; +} diff --git a/node_modules/yargs/build/lib/is-promise.d.ts b/node_modules/yargs/build/lib/is-promise.d.ts new file mode 100644 index 0000000..19b5566 --- /dev/null +++ b/node_modules/yargs/build/lib/is-promise.d.ts @@ -0,0 +1 @@ +export declare function isPromise(maybePromise: T | Promise): maybePromise is Promise; diff --git a/node_modules/yargs/build/lib/is-promise.js b/node_modules/yargs/build/lib/is-promise.js new file mode 100644 index 0000000..c24f9a8 --- /dev/null +++ b/node_modules/yargs/build/lib/is-promise.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isPromise = void 0; +function isPromise(maybePromise) { + return !!maybePromise && + !!maybePromise.then && + (typeof maybePromise.then === 'function'); +} +exports.isPromise = isPromise; diff --git a/node_modules/yargs/build/lib/levenshtein.d.ts b/node_modules/yargs/build/lib/levenshtein.d.ts new file mode 100644 index 0000000..08b6b7f --- /dev/null +++ b/node_modules/yargs/build/lib/levenshtein.d.ts @@ -0,0 +1 @@ +export declare function levenshtein(a: string, b: string): number; diff --git a/node_modules/yargs/build/lib/levenshtein.js b/node_modules/yargs/build/lib/levenshtein.js new file mode 100644 index 0000000..84c0831 --- /dev/null +++ b/node_modules/yargs/build/lib/levenshtein.js @@ -0,0 +1,58 @@ +"use strict"; +/* +Copyright (c) 2011 Andrei Mackenzie + +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. +*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.levenshtein = void 0; +// levenshtein distance algorithm, pulled from Andrei Mackenzie's MIT licensed. +// gist, which can be found here: https://gist.github.com/andrei-m/982927 +// Compute the edit distance between the two given strings +function levenshtein(a, b) { + if (a.length === 0) + return b.length; + if (b.length === 0) + return a.length; + const matrix = []; + // increment along the first column of each row + let i; + for (i = 0; i <= b.length; i++) { + matrix[i] = [i]; + } + // increment each column in the first row + let j; + for (j = 0; j <= a.length; j++) { + matrix[0][j] = j; + } + // Fill in the rest of the matrix + for (i = 1; i <= b.length; i++) { + for (j = 1; j <= a.length; j++) { + if (b.charAt(i - 1) === a.charAt(j - 1)) { + matrix[i][j] = matrix[i - 1][j - 1]; + } + else { + matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution + Math.min(matrix[i][j - 1] + 1, // insertion + matrix[i - 1][j] + 1)); // deletion + } + } + } + return matrix[b.length][a.length]; +} +exports.levenshtein = levenshtein; diff --git a/node_modules/yargs/build/lib/middleware.d.ts b/node_modules/yargs/build/lib/middleware.d.ts new file mode 100644 index 0000000..8fa7c34 --- /dev/null +++ b/node_modules/yargs/build/lib/middleware.d.ts @@ -0,0 +1,10 @@ +import { YargsInstance, Arguments } from './yargs'; +export declare function globalMiddlewareFactory(globalMiddleware: Middleware[], context: T): (callback: MiddlewareCallback | MiddlewareCallback[], applyBeforeValidation?: boolean) => T; +export declare function commandMiddlewareFactory(commandMiddleware?: MiddlewareCallback[]): Middleware[]; +export declare function applyMiddleware(argv: Arguments | Promise, yargs: YargsInstance, middlewares: Middleware[], beforeValidation: boolean): Arguments | Promise; +export interface MiddlewareCallback { + (argv: Arguments, yargs: YargsInstance): Partial | Promise>; +} +export interface Middleware extends MiddlewareCallback { + applyBeforeValidation: boolean; +} diff --git a/node_modules/yargs/build/lib/middleware.js b/node_modules/yargs/build/lib/middleware.js new file mode 100644 index 0000000..e93b6d2 --- /dev/null +++ b/node_modules/yargs/build/lib/middleware.js @@ -0,0 +1,57 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.applyMiddleware = exports.commandMiddlewareFactory = exports.globalMiddlewareFactory = void 0; +const argsert_1 = require("./argsert"); +const is_promise_1 = require("./is-promise"); +function globalMiddlewareFactory(globalMiddleware, context) { + return function (callback, applyBeforeValidation = false) { + argsert_1.argsert(' [boolean]', [callback, applyBeforeValidation], arguments.length); + if (Array.isArray(callback)) { + for (let i = 0; i < callback.length; i++) { + if (typeof callback[i] !== 'function') { + throw Error('middleware must be a function'); + } + callback[i].applyBeforeValidation = applyBeforeValidation; + } + Array.prototype.push.apply(globalMiddleware, callback); + } + else if (typeof callback === 'function') { + callback.applyBeforeValidation = applyBeforeValidation; + globalMiddleware.push(callback); + } + return context; + }; +} +exports.globalMiddlewareFactory = globalMiddlewareFactory; +function commandMiddlewareFactory(commandMiddleware) { + if (!commandMiddleware) + return []; + return commandMiddleware.map(middleware => { + middleware.applyBeforeValidation = false; + return middleware; + }); +} +exports.commandMiddlewareFactory = commandMiddlewareFactory; +function applyMiddleware(argv, yargs, middlewares, beforeValidation) { + const beforeValidationError = new Error('middleware cannot return a promise when applyBeforeValidation is true'); + return middlewares + .reduce((acc, middleware) => { + if (middleware.applyBeforeValidation !== beforeValidation) { + return acc; + } + if (is_promise_1.isPromise(acc)) { + return acc + .then(initialObj => Promise.all([initialObj, middleware(initialObj, yargs)])) + .then(([initialObj, middlewareObj]) => Object.assign(initialObj, middlewareObj)); + } + else { + const result = middleware(acc, yargs); + if (beforeValidation && is_promise_1.isPromise(result)) + throw beforeValidationError; + return is_promise_1.isPromise(result) + ? result.then(middlewareObj => Object.assign(acc, middlewareObj)) + : Object.assign(acc, result); + } + }, argv); +} +exports.applyMiddleware = applyMiddleware; diff --git a/node_modules/yargs/build/lib/obj-filter.d.ts b/node_modules/yargs/build/lib/obj-filter.d.ts new file mode 100644 index 0000000..031ae28 --- /dev/null +++ b/node_modules/yargs/build/lib/obj-filter.d.ts @@ -0,0 +1 @@ +export declare function objFilter(original?: T, filter?: (k: keyof T, v: T[keyof T]) => boolean): T; diff --git a/node_modules/yargs/build/lib/obj-filter.js b/node_modules/yargs/build/lib/obj-filter.js new file mode 100644 index 0000000..790f947 --- /dev/null +++ b/node_modules/yargs/build/lib/obj-filter.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.objFilter = void 0; +const common_types_1 = require("./common-types"); +function objFilter(original = {}, filter = () => true) { + const obj = {}; + common_types_1.objectKeys(original).forEach((key) => { + if (filter(key, original[key])) { + obj[key] = original[key]; + } + }); + return obj; +} +exports.objFilter = objFilter; diff --git a/node_modules/yargs/build/lib/parse-command.d.ts b/node_modules/yargs/build/lib/parse-command.d.ts new file mode 100644 index 0000000..fc57836 --- /dev/null +++ b/node_modules/yargs/build/lib/parse-command.d.ts @@ -0,0 +1,11 @@ +import { NotEmptyArray } from './common-types'; +export declare function parseCommand(cmd: string): ParsedCommand; +export interface ParsedCommand { + cmd: string; + demanded: Positional[]; + optional: Positional[]; +} +export interface Positional { + cmd: NotEmptyArray; + variadic: boolean; +} diff --git a/node_modules/yargs/build/lib/parse-command.js b/node_modules/yargs/build/lib/parse-command.js new file mode 100644 index 0000000..aaf2327 --- /dev/null +++ b/node_modules/yargs/build/lib/parse-command.js @@ -0,0 +1,36 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.parseCommand = void 0; +function parseCommand(cmd) { + const extraSpacesStrippedCommand = cmd.replace(/\s{2,}/g, ' '); + const splitCommand = extraSpacesStrippedCommand.split(/\s+(?![^[]*]|[^<]*>)/); + const bregex = /\.*[\][<>]/g; + const firstCommand = splitCommand.shift(); + if (!firstCommand) + throw new Error(`No command found in: ${cmd}`); + const parsedCommand = { + cmd: firstCommand.replace(bregex, ''), + demanded: [], + optional: [] + }; + splitCommand.forEach((cmd, i) => { + let variadic = false; + cmd = cmd.replace(/\s/g, ''); + if (/\.+[\]>]/.test(cmd) && i === splitCommand.length - 1) + variadic = true; + if (/^\[/.test(cmd)) { + parsedCommand.optional.push({ + cmd: cmd.replace(bregex, '').split('|'), + variadic + }); + } + else { + parsedCommand.demanded.push({ + cmd: cmd.replace(bregex, '').split('|'), + variadic + }); + } + }); + return parsedCommand; +} +exports.parseCommand = parseCommand; diff --git a/node_modules/yargs/build/lib/process-argv.d.ts b/node_modules/yargs/build/lib/process-argv.d.ts new file mode 100644 index 0000000..18fd43b --- /dev/null +++ b/node_modules/yargs/build/lib/process-argv.d.ts @@ -0,0 +1,2 @@ +export declare function getProcessArgvWithoutBin(): string[]; +export declare function getProcessArgvBin(): string; diff --git a/node_modules/yargs/build/lib/process-argv.js b/node_modules/yargs/build/lib/process-argv.js new file mode 100644 index 0000000..a9201dd --- /dev/null +++ b/node_modules/yargs/build/lib/process-argv.js @@ -0,0 +1,31 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getProcessArgvBin = exports.getProcessArgvWithoutBin = void 0; +function getProcessArgvBinIndex() { + // The binary name is the first command line argument for: + // - bundled Electron apps: bin argv1 argv2 ... argvn + if (isBundledElectronApp()) + return 0; + // or the second one (default) for: + // - standard node apps: node bin.js argv1 argv2 ... argvn + // - unbundled Electron apps: electron bin.js argv1 arg2 ... argvn + return 1; +} +function isBundledElectronApp() { + // process.defaultApp is either set by electron in an electron unbundled app, or undefined + // see https://github.com/electron/electron/blob/master/docs/api/process.md#processdefaultapp-readonly + return isElectronApp() && !process.defaultApp; +} +function isElectronApp() { + // process.versions.electron is either set by electron, or undefined + // see https://github.com/electron/electron/blob/master/docs/api/process.md#processversionselectron-readonly + return !!process.versions.electron; +} +function getProcessArgvWithoutBin() { + return process.argv.slice(getProcessArgvBinIndex() + 1); +} +exports.getProcessArgvWithoutBin = getProcessArgvWithoutBin; +function getProcessArgvBin() { + return process.argv[getProcessArgvBinIndex()]; +} +exports.getProcessArgvBin = getProcessArgvBin; diff --git a/node_modules/yargs/build/lib/usage.d.ts b/node_modules/yargs/build/lib/usage.d.ts new file mode 100644 index 0000000..d9dd1fa --- /dev/null +++ b/node_modules/yargs/build/lib/usage.d.ts @@ -0,0 +1,49 @@ +import { Dictionary } from './common-types'; +import { YargsInstance } from './yargs'; +import { YError } from './yerror'; +import { Y18N } from 'y18n'; +export declare function usage(yargs: YargsInstance, y18n: Y18N): UsageInstance; +/** Instance of the usage module. */ +export interface UsageInstance { + cacheHelpMessage(): void; + clearCachedHelpMessage(): void; + command(cmd: string, description: string | undefined, isDefault: boolean, aliases: string[], deprecated?: boolean): void; + deferY18nLookup(str: string): string; + describe(keys: string | string[] | Dictionary, desc?: string): void; + epilog(msg: string): void; + example(cmd: string, description?: string): void; + fail(msg?: string | null, err?: YError | string): void; + failFn(f: FailureFunction): void; + freeze(): void; + functionDescription(fn: { + name?: string; + }): string; + getCommands(): [string, string, boolean, string[], boolean][]; + getDescriptions(): Dictionary; + getPositionalGroupName(): string; + getUsage(): [string, string][]; + getUsageDisabled(): boolean; + help(): string; + reset(localLookup: Dictionary): UsageInstance; + showHelp(level: 'error' | 'log' | ((message: string) => void)): void; + showHelpOnFail(enabled?: boolean | string, message?: string): UsageInstance; + showVersion(): void; + stringifiedValues(values?: any[], separator?: string): string; + unfreeze(): void; + usage(msg: string | null, description?: string | false): UsageInstance; + version(ver: any): void; + wrap(cols: number | null | undefined): void; +} +export interface FailureFunction { + (msg: string | undefined | null, err: YError | string | undefined, usage: UsageInstance): void; +} +export interface FrozenUsageInstance { + failMessage: string | undefined | null; + failureOutput: boolean; + usages: [string, string][]; + usageDisabled: boolean; + epilogs: string[]; + examples: [string, string][]; + commands: [string, string, boolean, string[], boolean][]; + descriptions: Dictionary; +} diff --git a/node_modules/yargs/build/lib/usage.js b/node_modules/yargs/build/lib/usage.js new file mode 100644 index 0000000..73f7b24 --- /dev/null +++ b/node_modules/yargs/build/lib/usage.js @@ -0,0 +1,540 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.usage = void 0; +// this file handles outputting usage instructions, +// failures, etc. keeps logging in one place. +const common_types_1 = require("./common-types"); +const obj_filter_1 = require("./obj-filter"); +const path = require("path"); +const yerror_1 = require("./yerror"); +const decamelize = require("decamelize"); +const setBlocking = require("set-blocking"); +const stringWidth = require("string-width"); +function usage(yargs, y18n) { + const __ = y18n.__; + const self = {}; + // methods for ouputting/building failure message. + const fails = []; + self.failFn = function failFn(f) { + fails.push(f); + }; + let failMessage = null; + let showHelpOnFail = true; + self.showHelpOnFail = function showHelpOnFailFn(arg1 = true, arg2) { + function parseFunctionArgs() { + return typeof arg1 === 'string' ? [true, arg1] : [arg1, arg2]; + } + const [enabled, message] = parseFunctionArgs(); + failMessage = message; + showHelpOnFail = enabled; + return self; + }; + let failureOutput = false; + self.fail = function fail(msg, err) { + const logger = yargs._getLoggerInstance(); + if (fails.length) { + for (let i = fails.length - 1; i >= 0; --i) { + fails[i](msg, err, self); + } + } + else { + if (yargs.getExitProcess()) + setBlocking(true); + // don't output failure message more than once + if (!failureOutput) { + failureOutput = true; + if (showHelpOnFail) { + yargs.showHelp('error'); + logger.error(); + } + if (msg || err) + logger.error(msg || err); + if (failMessage) { + if (msg || err) + logger.error(''); + logger.error(failMessage); + } + } + err = err || new yerror_1.YError(msg); + if (yargs.getExitProcess()) { + return yargs.exit(1); + } + else if (yargs._hasParseCallback()) { + return yargs.exit(1, err); + } + else { + throw err; + } + } + }; + // methods for ouputting/building help (usage) message. + let usages = []; + let usageDisabled = false; + self.usage = (msg, description) => { + if (msg === null) { + usageDisabled = true; + usages = []; + return self; + } + usageDisabled = false; + usages.push([msg, description || '']); + return self; + }; + self.getUsage = () => { + return usages; + }; + self.getUsageDisabled = () => { + return usageDisabled; + }; + self.getPositionalGroupName = () => { + return __('Positionals:'); + }; + let examples = []; + self.example = (cmd, description) => { + examples.push([cmd, description || '']); + }; + let commands = []; + self.command = function command(cmd, description, isDefault, aliases, deprecated = false) { + // the last default wins, so cancel out any previously set default + if (isDefault) { + commands = commands.map((cmdArray) => { + cmdArray[2] = false; + return cmdArray; + }); + } + commands.push([cmd, description || '', isDefault, aliases, deprecated]); + }; + self.getCommands = () => commands; + let descriptions = {}; + self.describe = function describe(keyOrKeys, desc) { + if (Array.isArray(keyOrKeys)) { + keyOrKeys.forEach((k) => { + self.describe(k, desc); + }); + } + else if (typeof keyOrKeys === 'object') { + Object.keys(keyOrKeys).forEach((k) => { + self.describe(k, keyOrKeys[k]); + }); + } + else { + descriptions[keyOrKeys] = desc; + } + }; + self.getDescriptions = () => descriptions; + let epilogs = []; + self.epilog = (msg) => { + epilogs.push(msg); + }; + let wrapSet = false; + let wrap; + self.wrap = (cols) => { + wrapSet = true; + wrap = cols; + }; + function getWrap() { + if (!wrapSet) { + wrap = windowWidth(); + wrapSet = true; + } + return wrap; + } + const deferY18nLookupPrefix = '__yargsString__:'; + self.deferY18nLookup = str => deferY18nLookupPrefix + str; + self.help = function help() { + if (cachedHelpMessage) + return cachedHelpMessage; + normalizeAliases(); + // handle old demanded API + const base$0 = yargs.customScriptName ? yargs.$0 : path.basename(yargs.$0); + const demandedOptions = yargs.getDemandedOptions(); + const demandedCommands = yargs.getDemandedCommands(); + const deprecatedOptions = yargs.getDeprecatedOptions(); + const groups = yargs.getGroups(); + const options = yargs.getOptions(); + let keys = []; + keys = keys.concat(Object.keys(descriptions)); + keys = keys.concat(Object.keys(demandedOptions)); + keys = keys.concat(Object.keys(demandedCommands)); + keys = keys.concat(Object.keys(options.default)); + keys = keys.filter(filterHiddenOptions); + keys = Object.keys(keys.reduce((acc, key) => { + if (key !== '_') + acc[key] = true; + return acc; + }, {})); + const theWrap = getWrap(); + const ui = require('cliui')({ + width: theWrap, + wrap: !!theWrap + }); + // the usage string. + if (!usageDisabled) { + if (usages.length) { + // user-defined usage. + usages.forEach((usage) => { + ui.div(`${usage[0].replace(/\$0/g, base$0)}`); + if (usage[1]) { + ui.div({ text: `${usage[1]}`, padding: [1, 0, 0, 0] }); + } + }); + ui.div(); + } + else if (commands.length) { + let u = null; + // demonstrate how commands are used. + if (demandedCommands._) { + u = `${base$0} <${__('command')}>\n`; + } + else { + u = `${base$0} [${__('command')}]\n`; + } + ui.div(`${u}`); + } + } + // your application's commands, i.e., non-option + // arguments populated in '_'. + if (commands.length) { + ui.div(__('Commands:')); + const context = yargs.getContext(); + const parentCommands = context.commands.length ? `${context.commands.join(' ')} ` : ''; + if (yargs.getParserConfiguration()['sort-commands'] === true) { + commands = commands.sort((a, b) => a[0].localeCompare(b[0])); + } + commands.forEach((command) => { + const commandString = `${base$0} ${parentCommands}${command[0].replace(/^\$0 ?/, '')}`; // drop $0 from default commands. + ui.span({ + text: commandString, + padding: [0, 2, 0, 2], + width: maxWidth(commands, theWrap, `${base$0}${parentCommands}`) + 4 + }, { text: command[1] }); + const hints = []; + if (command[2]) + hints.push(`[${__('default')}]`); + if (command[3] && command[3].length) { + hints.push(`[${__('aliases:')} ${command[3].join(', ')}]`); + } + if (command[4]) { + if (typeof command[4] === 'string') { + hints.push(`[${__('deprecated: %s', command[4])}]`); + } + else { + hints.push(`[${__('deprecated')}]`); + } + } + if (hints.length) { + ui.div({ text: hints.join(' '), padding: [0, 0, 0, 2], align: 'right' }); + } + else { + ui.div(); + } + }); + ui.div(); + } + // perform some cleanup on the keys array, making it + // only include top-level keys not their aliases. + const aliasKeys = (Object.keys(options.alias) || []) + .concat(Object.keys(yargs.parsed.newAliases) || []); + keys = keys.filter(key => !yargs.parsed.newAliases[key] && aliasKeys.every(alias => (options.alias[alias] || []).indexOf(key) === -1)); + // populate 'Options:' group with any keys that have not + // explicitly had a group set. + const defaultGroup = __('Options:'); + if (!groups[defaultGroup]) + groups[defaultGroup] = []; + addUngroupedKeys(keys, options.alias, groups, defaultGroup); + // display 'Options:' table along with any custom tables: + Object.keys(groups).forEach((groupName) => { + if (!groups[groupName].length) + return; + // if we've grouped the key 'f', but 'f' aliases 'foobar', + // normalizedKeys should contain only 'foobar'. + const normalizedKeys = groups[groupName].filter(filterHiddenOptions).map((key) => { + if (~aliasKeys.indexOf(key)) + return key; + for (let i = 0, aliasKey; (aliasKey = aliasKeys[i]) !== undefined; i++) { + if (~(options.alias[aliasKey] || []).indexOf(key)) + return aliasKey; + } + return key; + }); + if (normalizedKeys.length < 1) + return; + ui.div(groupName); + // actually generate the switches string --foo, -f, --bar. + const switches = normalizedKeys.reduce((acc, key) => { + acc[key] = [key].concat(options.alias[key] || []) + .map(sw => { + // for the special positional group don't + // add '--' or '-' prefix. + if (groupName === self.getPositionalGroupName()) + return sw; + else { + return ( + // matches yargs-parser logic in which single-digits + // aliases declared with a boolean type are now valid + /^[0-9]$/.test(sw) + ? ~options.boolean.indexOf(key) ? '-' : '--' + : sw.length > 1 ? '--' : '-') + sw; + } + }) + .join(', '); + return acc; + }, {}); + normalizedKeys.forEach((key) => { + const kswitch = switches[key]; + let desc = descriptions[key] || ''; + let type = null; + if (~desc.lastIndexOf(deferY18nLookupPrefix)) + desc = __(desc.substring(deferY18nLookupPrefix.length)); + if (~options.boolean.indexOf(key)) + type = `[${__('boolean')}]`; + if (~options.count.indexOf(key)) + type = `[${__('count')}]`; + if (~options.string.indexOf(key)) + type = `[${__('string')}]`; + if (~options.normalize.indexOf(key)) + type = `[${__('string')}]`; + if (~options.array.indexOf(key)) + type = `[${__('array')}]`; + if (~options.number.indexOf(key)) + type = `[${__('number')}]`; + const deprecatedExtra = (deprecated) => typeof deprecated === 'string' + ? `[${__('deprecated: %s', deprecated)}]` + : `[${__('deprecated')}]`; + const extra = [ + (key in deprecatedOptions) ? deprecatedExtra(deprecatedOptions[key]) : null, + type, + (key in demandedOptions) ? `[${__('required')}]` : null, + options.choices && options.choices[key] ? `[${__('choices:')} ${self.stringifiedValues(options.choices[key])}]` : null, + defaultString(options.default[key], options.defaultDescription[key]) + ].filter(Boolean).join(' '); + ui.span({ text: kswitch, padding: [0, 2, 0, 2], width: maxWidth(switches, theWrap) + 4 }, desc); + if (extra) + ui.div({ text: extra, padding: [0, 0, 0, 2], align: 'right' }); + else + ui.div(); + }); + ui.div(); + }); + // describe some common use-cases for your application. + if (examples.length) { + ui.div(__('Examples:')); + examples.forEach((example) => { + example[0] = example[0].replace(/\$0/g, base$0); + }); + examples.forEach((example) => { + if (example[1] === '') { + ui.div({ + text: example[0], + padding: [0, 2, 0, 2] + }); + } + else { + ui.div({ + text: example[0], + padding: [0, 2, 0, 2], + width: maxWidth(examples, theWrap) + 4 + }, { + text: example[1] + }); + } + }); + ui.div(); + } + // the usage string. + if (epilogs.length > 0) { + const e = epilogs.map(epilog => epilog.replace(/\$0/g, base$0)).join('\n'); + ui.div(`${e}\n`); + } + // Remove the trailing white spaces + return ui.toString().replace(/\s*$/, ''); + }; + // return the maximum width of a string + // in the left-hand column of a table. + function maxWidth(table, theWrap, modifier) { + let width = 0; + // table might be of the form [leftColumn], + // or {key: leftColumn} + if (!Array.isArray(table)) { + table = Object.values(table).map(v => [v]); + } + table.forEach((v) => { + width = Math.max(stringWidth(modifier ? `${modifier} ${v[0]}` : v[0]), width); + }); + // if we've enabled 'wrap' we should limit + // the max-width of the left-column. + if (theWrap) + width = Math.min(width, parseInt((theWrap * 0.5).toString(), 10)); + return width; + } + // make sure any options set for aliases, + // are copied to the keys being aliased. + function normalizeAliases() { + // handle old demanded API + const demandedOptions = yargs.getDemandedOptions(); + const options = yargs.getOptions(); + (Object.keys(options.alias) || []).forEach((key) => { + options.alias[key].forEach((alias) => { + // copy descriptions. + if (descriptions[alias]) + self.describe(key, descriptions[alias]); + // copy demanded. + if (alias in demandedOptions) + yargs.demandOption(key, demandedOptions[alias]); + // type messages. + if (~options.boolean.indexOf(alias)) + yargs.boolean(key); + if (~options.count.indexOf(alias)) + yargs.count(key); + if (~options.string.indexOf(alias)) + yargs.string(key); + if (~options.normalize.indexOf(alias)) + yargs.normalize(key); + if (~options.array.indexOf(alias)) + yargs.array(key); + if (~options.number.indexOf(alias)) + yargs.number(key); + }); + }); + } + // if yargs is executing an async handler, we take a snapshot of the + // help message to display on failure: + let cachedHelpMessage; + self.cacheHelpMessage = function () { + cachedHelpMessage = this.help(); + }; + // however this snapshot must be cleared afterwards + // not to be be used by next calls to parse + self.clearCachedHelpMessage = function () { + cachedHelpMessage = undefined; + }; + // given a set of keys, place any keys that are + // ungrouped under the 'Options:' grouping. + function addUngroupedKeys(keys, aliases, groups, defaultGroup) { + let groupedKeys = []; + let toCheck = null; + Object.keys(groups).forEach((group) => { + groupedKeys = groupedKeys.concat(groups[group]); + }); + keys.forEach((key) => { + toCheck = [key].concat(aliases[key]); + if (!toCheck.some(k => groupedKeys.indexOf(k) !== -1)) { + groups[defaultGroup].push(key); + } + }); + return groupedKeys; + } + function filterHiddenOptions(key) { + return yargs.getOptions().hiddenOptions.indexOf(key) < 0 || yargs.parsed.argv[yargs.getOptions().showHiddenOpt]; + } + self.showHelp = (level) => { + const logger = yargs._getLoggerInstance(); + if (!level) + level = 'error'; + const emit = typeof level === 'function' ? level : logger[level]; + emit(self.help()); + }; + self.functionDescription = (fn) => { + const description = fn.name ? decamelize(fn.name, '-') : __('generated-value'); + return ['(', description, ')'].join(''); + }; + self.stringifiedValues = function stringifiedValues(values, separator) { + let string = ''; + const sep = separator || ', '; + const array = [].concat(values); + if (!values || !array.length) + return string; + array.forEach((value) => { + if (string.length) + string += sep; + string += JSON.stringify(value); + }); + return string; + }; + // format the default-value-string displayed in + // the right-hand column. + function defaultString(value, defaultDescription) { + let string = `[${__('default:')} `; + if (value === undefined && !defaultDescription) + return null; + if (defaultDescription) { + string += defaultDescription; + } + else { + switch (typeof value) { + case 'string': + string += `"${value}"`; + break; + case 'object': + string += JSON.stringify(value); + break; + default: + string += value; + } + } + return `${string}]`; + } + // guess the width of the console window, max-width 80. + function windowWidth() { + const maxWidth = 80; + // CI is not a TTY + /* c8 ignore next 2 */ + if (typeof process === 'object' && process.stdout && process.stdout.columns) { + return Math.min(maxWidth, process.stdout.columns); + } + else { + return maxWidth; + } + } + // logic for displaying application version. + let version = null; + self.version = (ver) => { + version = ver; + }; + self.showVersion = () => { + const logger = yargs._getLoggerInstance(); + logger.log(version); + }; + self.reset = function reset(localLookup) { + // do not reset wrap here + // do not reset fails here + failMessage = null; + failureOutput = false; + usages = []; + usageDisabled = false; + epilogs = []; + examples = []; + commands = []; + descriptions = obj_filter_1.objFilter(descriptions, k => !localLookup[k]); + return self; + }; + const frozens = []; + self.freeze = function freeze() { + frozens.push({ + failMessage, + failureOutput, + usages, + usageDisabled, + epilogs, + examples, + commands, + descriptions + }); + }; + self.unfreeze = function unfreeze() { + const frozen = frozens.pop(); + common_types_1.assertNotStrictEqual(frozen, undefined); + ({ + failMessage, + failureOutput, + usages, + usageDisabled, + epilogs, + examples, + commands, + descriptions + } = frozen); + }; + return self; +} +exports.usage = usage; diff --git a/node_modules/yargs/build/lib/validation.d.ts b/node_modules/yargs/build/lib/validation.d.ts new file mode 100644 index 0000000..e2d7854 --- /dev/null +++ b/node_modules/yargs/build/lib/validation.d.ts @@ -0,0 +1,34 @@ +import { Dictionary } from './common-types'; +import { UsageInstance } from './usage'; +import { YargsInstance, Arguments } from './yargs'; +import { DetailedArguments } from 'yargs-parser'; +import { Y18N } from 'y18n'; +export declare function validation(yargs: YargsInstance, usage: UsageInstance, y18n: Y18N): ValidationInstance; +/** Instance of the validation module. */ +export interface ValidationInstance { + check(f: CustomCheck['func'], global: boolean): void; + conflicting(argv: Arguments): void; + conflicts(key: string | Dictionary, value?: string | string[]): void; + customChecks(argv: Arguments, aliases: DetailedArguments['aliases']): void; + freeze(): void; + getConflicting(): Dictionary<(string | undefined)[]>; + getImplied(): Dictionary; + implications(argv: Arguments): void; + implies(key: string | Dictionary, value?: KeyOrPos | KeyOrPos[]): void; + isValidAndSomeAliasIsNotNew(key: string, aliases: DetailedArguments['aliases']): boolean; + limitedChoices(argv: Arguments): void; + nonOptionCount(argv: Arguments): void; + positionalCount(required: number, observed: number): void; + recommendCommands(cmd: string, potentialCommands: string[]): void; + requiredArguments(argv: Arguments): void; + reset(localLookup: Dictionary): ValidationInstance; + unfreeze(): void; + unknownArguments(argv: Arguments, aliases: DetailedArguments['aliases'], positionalMap: Dictionary, isDefaultCommand: boolean): void; + unknownCommands(argv: Arguments): boolean; +} +interface CustomCheck { + func: (argv: Arguments, aliases: DetailedArguments['aliases']) => any; + global: boolean; +} +export declare type KeyOrPos = string | number; +export {}; diff --git a/node_modules/yargs/build/lib/validation.js b/node_modules/yargs/build/lib/validation.js new file mode 100644 index 0000000..60c5e43 --- /dev/null +++ b/node_modules/yargs/build/lib/validation.js @@ -0,0 +1,330 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.validation = void 0; +const argsert_1 = require("./argsert"); +const common_types_1 = require("./common-types"); +const levenshtein_1 = require("./levenshtein"); +const obj_filter_1 = require("./obj-filter"); +const specialKeys = ['$0', '--', '_']; +// validation-type-stuff, missing params, +// bad implications, custom checks. +function validation(yargs, usage, y18n) { + const __ = y18n.__; + const __n = y18n.__n; + const self = {}; + // validate appropriate # of non-option + // arguments were provided, i.e., '_'. + self.nonOptionCount = function nonOptionCount(argv) { + const demandedCommands = yargs.getDemandedCommands(); + // don't count currently executing commands + const _s = argv._.length - yargs.getContext().commands.length; + if (demandedCommands._ && (_s < demandedCommands._.min || _s > demandedCommands._.max)) { + if (_s < demandedCommands._.min) { + if (demandedCommands._.minMsg !== undefined) { + usage.fail( + // replace $0 with observed, $1 with expected. + demandedCommands._.minMsg + ? demandedCommands._.minMsg.replace(/\$0/g, _s.toString()).replace(/\$1/, demandedCommands._.min.toString()) + : null); + } + else { + usage.fail(__n('Not enough non-option arguments: got %s, need at least %s', 'Not enough non-option arguments: got %s, need at least %s', _s, _s, demandedCommands._.min)); + } + } + else if (_s > demandedCommands._.max) { + if (demandedCommands._.maxMsg !== undefined) { + usage.fail( + // replace $0 with observed, $1 with expected. + demandedCommands._.maxMsg + ? demandedCommands._.maxMsg.replace(/\$0/g, _s.toString()).replace(/\$1/, demandedCommands._.max.toString()) + : null); + } + else { + usage.fail(__n('Too many non-option arguments: got %s, maximum of %s', 'Too many non-option arguments: got %s, maximum of %s', _s, _s, demandedCommands._.max)); + } + } + } + }; + // validate the appropriate # of + // positional arguments were provided: + self.positionalCount = function positionalCount(required, observed) { + if (observed < required) { + usage.fail(__n('Not enough non-option arguments: got %s, need at least %s', 'Not enough non-option arguments: got %s, need at least %s', observed, observed, required)); + } + }; + // make sure all the required arguments are present. + self.requiredArguments = function requiredArguments(argv) { + const demandedOptions = yargs.getDemandedOptions(); + let missing = null; + for (const key of Object.keys(demandedOptions)) { + if (!Object.prototype.hasOwnProperty.call(argv, key) || typeof argv[key] === 'undefined') { + missing = missing || {}; + missing[key] = demandedOptions[key]; + } + } + if (missing) { + const customMsgs = []; + for (const key of Object.keys(missing)) { + const msg = missing[key]; + if (msg && customMsgs.indexOf(msg) < 0) { + customMsgs.push(msg); + } + } + const customMsg = customMsgs.length ? `\n${customMsgs.join('\n')}` : ''; + usage.fail(__n('Missing required argument: %s', 'Missing required arguments: %s', Object.keys(missing).length, Object.keys(missing).join(', ') + customMsg)); + } + }; + // check for unknown arguments (strict-mode). + self.unknownArguments = function unknownArguments(argv, aliases, positionalMap, isDefaultCommand) { + const commandKeys = yargs.getCommandInstance().getCommands(); + const unknown = []; + const currentContext = yargs.getContext(); + Object.keys(argv).forEach((key) => { + if (specialKeys.indexOf(key) === -1 && + !Object.prototype.hasOwnProperty.call(positionalMap, key) && + !Object.prototype.hasOwnProperty.call(yargs._getParseContext(), key) && + !self.isValidAndSomeAliasIsNotNew(key, aliases)) { + unknown.push(key); + } + }); + if ((currentContext.commands.length > 0) || (commandKeys.length > 0) || isDefaultCommand) { + argv._.slice(currentContext.commands.length).forEach((key) => { + if (commandKeys.indexOf(key) === -1) { + unknown.push(key); + } + }); + } + if (unknown.length > 0) { + usage.fail(__n('Unknown argument: %s', 'Unknown arguments: %s', unknown.length, unknown.join(', '))); + } + }; + self.unknownCommands = function unknownCommands(argv) { + const commandKeys = yargs.getCommandInstance().getCommands(); + const unknown = []; + const currentContext = yargs.getContext(); + if ((currentContext.commands.length > 0) || (commandKeys.length > 0)) { + argv._.slice(currentContext.commands.length).forEach((key) => { + if (commandKeys.indexOf(key) === -1) { + unknown.push(key); + } + }); + } + if (unknown.length > 0) { + usage.fail(__n('Unknown command: %s', 'Unknown commands: %s', unknown.length, unknown.join(', '))); + return true; + } + else { + return false; + } + }; + // check for a key that is not an alias, or for which every alias is new, + // implying that it was invented by the parser, e.g., during camelization + self.isValidAndSomeAliasIsNotNew = function isValidAndSomeAliasIsNotNew(key, aliases) { + if (!Object.prototype.hasOwnProperty.call(aliases, key)) { + return false; + } + const newAliases = yargs.parsed.newAliases; + for (const a of [key, ...aliases[key]]) { + if (!Object.prototype.hasOwnProperty.call(newAliases, a) || !newAliases[key]) { + return true; + } + } + return false; + }; + // validate arguments limited to enumerated choices + self.limitedChoices = function limitedChoices(argv) { + const options = yargs.getOptions(); + const invalid = {}; + if (!Object.keys(options.choices).length) + return; + Object.keys(argv).forEach((key) => { + if (specialKeys.indexOf(key) === -1 && + Object.prototype.hasOwnProperty.call(options.choices, key)) { + [].concat(argv[key]).forEach((value) => { + // TODO case-insensitive configurability + if (options.choices[key].indexOf(value) === -1 && + value !== undefined) { + invalid[key] = (invalid[key] || []).concat(value); + } + }); + } + }); + const invalidKeys = Object.keys(invalid); + if (!invalidKeys.length) + return; + let msg = __('Invalid values:'); + invalidKeys.forEach((key) => { + msg += `\n ${__('Argument: %s, Given: %s, Choices: %s', key, usage.stringifiedValues(invalid[key]), usage.stringifiedValues(options.choices[key]))}`; + }); + usage.fail(msg); + }; + // custom checks, added using the `check` option on yargs. + let checks = []; + self.check = function check(f, global) { + checks.push({ + func: f, + global + }); + }; + self.customChecks = function customChecks(argv, aliases) { + for (let i = 0, f; (f = checks[i]) !== undefined; i++) { + const func = f.func; + let result = null; + try { + result = func(argv, aliases); + } + catch (err) { + usage.fail(err.message ? err.message : err, err); + continue; + } + if (!result) { + usage.fail(__('Argument check failed: %s', func.toString())); + } + else if (typeof result === 'string' || result instanceof Error) { + usage.fail(result.toString(), result); + } + } + }; + // check implications, argument foo implies => argument bar. + let implied = {}; + self.implies = function implies(key, value) { + argsert_1.argsert(' [array|number|string]', [key, value], arguments.length); + if (typeof key === 'object') { + Object.keys(key).forEach((k) => { + self.implies(k, key[k]); + }); + } + else { + yargs.global(key); + if (!implied[key]) { + implied[key] = []; + } + if (Array.isArray(value)) { + value.forEach((i) => self.implies(key, i)); + } + else { + common_types_1.assertNotStrictEqual(value, undefined); + implied[key].push(value); + } + } + }; + self.getImplied = function getImplied() { + return implied; + }; + function keyExists(argv, val) { + // convert string '1' to number 1 + const num = Number(val); + val = isNaN(num) ? val : num; + if (typeof val === 'number') { + // check length of argv._ + val = argv._.length >= val; + } + else if (val.match(/^--no-.+/)) { + // check if key/value doesn't exist + val = val.match(/^--no-(.+)/)[1]; + val = !argv[val]; + } + else { + // check if key/value exists + val = argv[val]; + } + return val; + } + self.implications = function implications(argv) { + const implyFail = []; + Object.keys(implied).forEach((key) => { + const origKey = key; + (implied[key] || []).forEach((value) => { + let key = origKey; + const origValue = value; + key = keyExists(argv, key); + value = keyExists(argv, value); + if (key && !value) { + implyFail.push(` ${origKey} -> ${origValue}`); + } + }); + }); + if (implyFail.length) { + let msg = `${__('Implications failed:')}\n`; + implyFail.forEach((value) => { + msg += (value); + }); + usage.fail(msg); + } + }; + let conflicting = {}; + self.conflicts = function conflicts(key, value) { + argsert_1.argsert(' [array|string]', [key, value], arguments.length); + if (typeof key === 'object') { + Object.keys(key).forEach((k) => { + self.conflicts(k, key[k]); + }); + } + else { + yargs.global(key); + if (!conflicting[key]) { + conflicting[key] = []; + } + if (Array.isArray(value)) { + value.forEach((i) => self.conflicts(key, i)); + } + else { + conflicting[key].push(value); + } + } + }; + self.getConflicting = () => conflicting; + self.conflicting = function conflictingFn(argv) { + Object.keys(argv).forEach((key) => { + if (conflicting[key]) { + conflicting[key].forEach((value) => { + // we default keys to 'undefined' that have been configured, we should not + // apply conflicting check unless they are a value other than 'undefined'. + if (value && argv[key] !== undefined && argv[value] !== undefined) { + usage.fail(__('Arguments %s and %s are mutually exclusive', key, value)); + } + }); + } + }); + }; + self.recommendCommands = function recommendCommands(cmd, potentialCommands) { + const threshold = 3; // if it takes more than three edits, let's move on. + potentialCommands = potentialCommands.sort((a, b) => b.length - a.length); + let recommended = null; + let bestDistance = Infinity; + for (let i = 0, candidate; (candidate = potentialCommands[i]) !== undefined; i++) { + const d = levenshtein_1.levenshtein(cmd, candidate); + if (d <= threshold && d < bestDistance) { + bestDistance = d; + recommended = candidate; + } + } + if (recommended) + usage.fail(__('Did you mean %s?', recommended)); + }; + self.reset = function reset(localLookup) { + implied = obj_filter_1.objFilter(implied, k => !localLookup[k]); + conflicting = obj_filter_1.objFilter(conflicting, k => !localLookup[k]); + checks = checks.filter(c => c.global); + return self; + }; + const frozens = []; + self.freeze = function freeze() { + frozens.push({ + implied, + checks, + conflicting + }); + }; + self.unfreeze = function unfreeze() { + const frozen = frozens.pop(); + common_types_1.assertNotStrictEqual(frozen, undefined); + ({ + implied, + checks, + conflicting + } = frozen); + }; + return self; +} +exports.validation = validation; diff --git a/node_modules/yargs/build/lib/yargs.d.ts b/node_modules/yargs/build/lib/yargs.d.ts new file mode 100644 index 0000000..8e6e27c --- /dev/null +++ b/node_modules/yargs/build/lib/yargs.d.ts @@ -0,0 +1,274 @@ +/// +import { CommandInstance, CommandHandler, CommandBuilderDefinition, CommandBuilder, CommandHandlerCallback, FinishCommandHandler } from './command'; +import { Dictionary } from './common-types'; +import { Arguments as ParserArguments, DetailedArguments as ParserDetailedArguments, Configuration as ParserConfiguration, Options as ParserOptions, ConfigCallback, CoerceCallback } from 'yargs-parser'; +import { YError } from './yerror'; +import { UsageInstance, FailureFunction } from './usage'; +import { CompletionFunction } from './completion'; +import { ValidationInstance, KeyOrPos } from './validation'; +import { Y18N } from 'y18n'; +import { MiddlewareCallback, Middleware } from './middleware'; +import { RequireDirectoryOptions } from 'require-directory'; +export declare function Yargs(processArgs?: string | string[], cwd?: string, parentRequire?: NodeRequire): YargsInstance; +export declare function rebase(base: string, dir: string): string; +/** Instance of the yargs module. */ +export interface YargsInstance { + $0: string; + argv: Arguments; + customScriptName: boolean; + parsed: DetailedArguments | false; + _copyDoubleDash>(argv: T): T; + _getLoggerInstance(): LoggerInstance; + _getParseContext(): Object; + _hasOutput(): boolean; + _hasParseCallback(): boolean; + _parseArgs: { + (args: null, shortCircuit: null, _calledFromCommand: boolean, commandIndex?: number): Arguments | Promise; + (args: string | string[], shortCircuit?: boolean): Arguments | Promise; + }; + _runValidation(argv: Arguments, aliases: Dictionary, positionalMap: Dictionary, parseErrors: Error | null, isDefaultCommand?: boolean): void; + _setHasOutput(): void; + addHelpOpt: { + (opt?: string | false): YargsInstance; + (opt?: string, msg?: string): YargsInstance; + }; + addShowHiddenOpt: { + (opt?: string | false): YargsInstance; + (opt?: string, msg?: string): YargsInstance; + }; + alias: { + (keys: string | string[], aliases: string | string[]): YargsInstance; + (keyAliases: Dictionary): YargsInstance; + }; + array(keys: string | string[]): YargsInstance; + boolean(keys: string | string[]): YargsInstance; + check(f: (argv: Arguments, aliases: Dictionary) => any, _global?: boolean): YargsInstance; + choices: { + (keys: string | string[], choices: string | string[]): YargsInstance; + (keyChoices: Dictionary): YargsInstance; + }; + coerce: { + (keys: string | string[], coerceCallback: CoerceCallback): YargsInstance; + (keyCoerceCallbacks: Dictionary): YargsInstance; + }; + command(cmd: string | string[], description: CommandHandler['description'], builder?: CommandBuilderDefinition | CommandBuilder, handler?: CommandHandlerCallback, commandMiddleware?: Middleware[], deprecated?: boolean): YargsInstance; + commandDir(dir: string, opts?: RequireDirectoryOptions): YargsInstance; + completion: { + (cmd?: string, fn?: CompletionFunction): YargsInstance; + (cmd?: string, desc?: string | false, fn?: CompletionFunction): YargsInstance; + }; + config: { + (config: Dictionary): YargsInstance; + (keys?: string | string[], configCallback?: ConfigCallback): YargsInstance; + (keys?: string | string[], msg?: string, configCallback?: ConfigCallback): YargsInstance; + }; + conflicts: { + (key: string, conflictsWith: string | string[]): YargsInstance; + (keyConflicts: Dictionary): YargsInstance; + }; + count(keys: string | string[]): YargsInstance; + default: { + (key: string, value: any, defaultDescription?: string): YargsInstance; + (keys: string[], value: Exclude): YargsInstance; + (keys: Dictionary): YargsInstance; + }; + defaults: YargsInstance['default']; + demand: { + (min: number, max?: number | string, msg?: string): YargsInstance; + (keys: string | string[], msg?: string | true): YargsInstance; + (keys: string | string[], max: string[], msg?: string | true): YargsInstance; + (keyMsgs: Dictionary): YargsInstance; + (keyMsgs: Dictionary, max: string[], msg?: string): YargsInstance; + }; + demandCommand(): YargsInstance; + demandCommand(min: number, minMsg?: string): YargsInstance; + demandCommand(min: number, max: number, minMsg?: string | null, maxMsg?: string | null): YargsInstance; + demandOption: { + (keys: string | string[], msg?: string): YargsInstance; + (keyMsgs: Dictionary): YargsInstance; + }; + deprecateOption(option: string, message?: string | boolean): YargsInstance; + describe: { + (keys: string | string[], description?: string): YargsInstance; + (keyDescriptions: Dictionary): YargsInstance; + }; + detectLocale(detect: boolean): YargsInstance; + env(prefix?: string | false): YargsInstance; + epilog: YargsInstance['epilogue']; + epilogue(msg: string): YargsInstance; + example(cmd: string | [string, string?][], description?: string): YargsInstance; + exit(code: number, err?: YError | string): void; + exitProcess(enabled: boolean): YargsInstance; + fail(f: FailureFunction): YargsInstance; + getCommandInstance(): CommandInstance; + getCompletion(args: string[], done: (completions: string[]) => any): void; + getContext(): Context; + getDemandedCommands(): Options['demandedCommands']; + getDemandedOptions(): Options['demandedOptions']; + getDeprecatedOptions(): Options['deprecatedOptions']; + getDetectLocale(): boolean; + getExitProcess(): boolean; + getGroups(): Dictionary; + getHandlerFinishCommand(): FinishCommandHandler | null; + getOptions(): Options; + getParserConfiguration(): Configuration; + getStrict(): boolean; + getStrictCommands(): boolean; + getUsageInstance(): UsageInstance; + getValidationInstance(): ValidationInstance; + global(keys: string | string[], global?: boolean): YargsInstance; + group(keys: string | string[], groupName: string): YargsInstance; + help: YargsInstance['addHelpOpt']; + hide(key: string): YargsInstance; + implies: { + (key: string, implication: KeyOrPos | KeyOrPos[]): YargsInstance; + (keyImplications: Dictionary): YargsInstance; + }; + locale: { + (): string; + (locale: string): YargsInstance; + }; + middleware(callback: MiddlewareCallback | MiddlewareCallback[], applyBeforeValidation?: boolean): YargsInstance; + nargs: { + (keys: string | string[], nargs: number): YargsInstance; + (keyNargs: Dictionary): YargsInstance; + }; + normalize(keys: string | string[]): YargsInstance; + number(keys: string | string[]): YargsInstance; + onFinishCommand(f: FinishCommandHandler): YargsInstance; + option: { + (key: string, optionDefinition: OptionDefinition): YargsInstance; + (keyOptionDefinitions: Dictionary): YargsInstance; + }; + options: YargsInstance['option']; + parse: { + (): Arguments | Promise; + (args: string | string[], context: object, parseCallback?: ParseCallback): Arguments | Promise; + (args: string | string[], parseCallback: ParseCallback): Arguments | Promise; + (args: string | string[], shortCircuit: boolean): Arguments | Promise; + }; + parserConfiguration(config: Configuration): YargsInstance; + pkgConf(key: string, rootPath?: string): YargsInstance; + positional(key: string, positionalDefinition: PositionalDefinition): YargsInstance; + recommendCommands(recommend: boolean): YargsInstance; + require: YargsInstance['demand']; + required: YargsInstance['demand']; + requiresArg(keys: string | string[] | Dictionary): YargsInstance; + reset(aliases?: DetailedArguments['aliases']): YargsInstance; + resetOptions(aliases?: DetailedArguments['aliases']): YargsInstance; + scriptName(scriptName: string): YargsInstance; + showCompletionScript($0?: string, cmd?: string): YargsInstance; + showHelp(level: 'error' | 'log' | ((message: string) => void)): YargsInstance; + showHelpOnFail: { + (message?: string): YargsInstance; + (enabled: boolean, message: string): YargsInstance; + }; + showHidden: YargsInstance['addShowHiddenOpt']; + skipValidation(keys: string | string[]): YargsInstance; + strict(enable?: boolean): YargsInstance; + strictCommands(enable?: boolean): YargsInstance; + string(key: string | string[]): YargsInstance; + terminalWidth(): number | null; + updateStrings(obj: Dictionary): YargsInstance; + updateLocale: YargsInstance['updateStrings']; + usage: { + (msg: string | null): YargsInstance; + (msg: string, description: CommandHandler['description'], builder?: CommandBuilderDefinition | CommandBuilder, handler?: CommandHandlerCallback): YargsInstance; + }; + version: { + (ver?: string | false): YargsInstance; + (key?: string, ver?: string): YargsInstance; + (key?: string, msg?: string, ver?: string): YargsInstance; + }; + wrap(cols: number | null | undefined): YargsInstance; +} +export declare function isYargsInstance(y: YargsInstance | void): y is YargsInstance; +/** Yargs' context. */ +export interface Context { + commands: string[]; + files: string[]; + fullCommands: string[]; +} +declare type LoggerInstance = Pick; +export interface Options extends ParserOptions { + __: Y18N['__']; + alias: Dictionary; + array: string[]; + boolean: string[]; + choices: Dictionary; + config: Dictionary; + configObjects: Dictionary[]; + configuration: Configuration; + count: string[]; + defaultDescription: Dictionary; + demandedCommands: Dictionary<{ + min: number; + max: number; + minMsg?: string | null; + maxMsg?: string | null; + }>; + demandedOptions: Dictionary; + deprecatedOptions: Dictionary; + hiddenOptions: string[]; + /** Manually set keys */ + key: Dictionary; + local: string[]; + normalize: string[]; + number: string[]; + showHiddenOpt: string; + skipValidation: string[]; + string: string[]; +} +export interface Configuration extends Partial { + /** Should a config object be deep-merged with the object config it extends? */ + 'deep-merge-config'?: boolean; + /** Should commands be sorted in help? */ + 'sort-commands'?: boolean; +} +export interface OptionDefinition { + alias?: string | string[]; + array?: boolean; + boolean?: boolean; + choices?: string | string[]; + coerce?: CoerceCallback; + config?: boolean; + configParser?: ConfigCallback; + conflicts?: string | string[]; + count?: boolean; + default?: any; + defaultDescription?: string; + deprecate?: string | boolean; + deprecated?: OptionDefinition['deprecate']; + desc?: string; + describe?: OptionDefinition['desc']; + description?: OptionDefinition['desc']; + demand?: string | true; + demandOption?: OptionDefinition['demand']; + global?: boolean; + group?: string; + hidden?: boolean; + implies?: string | number | KeyOrPos[]; + nargs?: number; + normalize?: boolean; + number?: boolean; + require?: OptionDefinition['demand']; + required?: OptionDefinition['demand']; + requiresArg?: boolean; + skipValidation?: boolean; + string?: boolean; + type?: 'array' | 'boolean' | 'count' | 'number' | 'string'; +} +interface PositionalDefinition extends Pick { + type?: 'boolean' | 'number' | 'string'; +} +interface ParseCallback { + (err: YError | string | undefined | null, argv: Arguments | Promise, output: string): void; +} +export interface Arguments extends ParserArguments { + /** The script name or node command */ + $0: string; +} +export interface DetailedArguments extends ParserDetailedArguments { + argv: Arguments; +} +export {}; diff --git a/node_modules/yargs/build/lib/yargs.js b/node_modules/yargs/build/lib/yargs.js new file mode 100644 index 0000000..316f3d6 --- /dev/null +++ b/node_modules/yargs/build/lib/yargs.js @@ -0,0 +1,1190 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isYargsInstance = exports.rebase = exports.Yargs = void 0; +const command_1 = require("./command"); +const common_types_1 = require("./common-types"); +const yerror_1 = require("./yerror"); +const usage_1 = require("./usage"); +const argsert_1 = require("./argsert"); +const fs = require("fs"); +const completion_1 = require("./completion"); +const path = require("path"); +const validation_1 = require("./validation"); +const obj_filter_1 = require("./obj-filter"); +const apply_extends_1 = require("./apply-extends"); +const middleware_1 = require("./middleware"); +const processArgv = require("./process-argv"); +const is_promise_1 = require("./is-promise"); +const Parser = require("yargs-parser"); +const y18nFactory = require("y18n"); +const setBlocking = require("set-blocking"); +const findUp = require("find-up"); +const requireMainFilename = require("require-main-filename"); +function Yargs(processArgs = [], cwd = process.cwd(), parentRequire = require) { + const self = {}; + let command; + let completion = null; + let groups = {}; + const globalMiddleware = []; + let output = ''; + const preservedGroups = {}; + let usage; + let validation; + let handlerFinishCommand = null; + const y18n = y18nFactory({ + directory: path.resolve(__dirname, '../../locales'), + updateFiles: false + }); + self.middleware = middleware_1.globalMiddlewareFactory(globalMiddleware, self); + self.scriptName = function (scriptName) { + self.customScriptName = true; + self.$0 = scriptName; + return self; + }; + // ignore the node bin, specify this in your + // bin file with #!/usr/bin/env node + let default$0; + if (/\b(node|iojs|electron)(\.exe)?$/.test(process.argv[0])) { + default$0 = process.argv.slice(1, 2); + } + else { + default$0 = process.argv.slice(0, 1); + } + self.$0 = default$0 + .map(x => { + const b = rebase(cwd, x); + return x.match(/^(\/|([a-zA-Z]:)?\\)/) && b.length < x.length ? b : x; + }) + .join(' ').trim(); + if (process.env._ !== undefined && processArgv.getProcessArgvBin() === process.env._) { + self.$0 = process.env._.replace(`${path.dirname(process.execPath)}/`, ''); + } + // use context object to keep track of resets, subcommand execution, etc + // submodules should modify and check the state of context as necessary + const context = { resets: -1, commands: [], fullCommands: [], files: [] }; + self.getContext = () => context; + // puts yargs back into an initial state. any keys + // that have been set to "global" will not be reset + // by this action. + let options; + self.resetOptions = self.reset = function resetOptions(aliases = {}) { + context.resets++; + options = options || {}; + // put yargs back into an initial state, this + // logic is used to build a nested command + // hierarchy. + const tmpOptions = {}; + tmpOptions.local = options.local ? options.local : []; + tmpOptions.configObjects = options.configObjects ? options.configObjects : []; + // if a key has been explicitly set as local, + // we should reset it before passing options to command. + const localLookup = {}; + tmpOptions.local.forEach((l) => { + localLookup[l] = true; + (aliases[l] || []).forEach((a) => { + localLookup[a] = true; + }); + }); + // add all groups not set to local to preserved groups + Object.assign(preservedGroups, Object.keys(groups).reduce((acc, groupName) => { + const keys = groups[groupName].filter(key => !(key in localLookup)); + if (keys.length > 0) { + acc[groupName] = keys; + } + return acc; + }, {})); + // groups can now be reset + groups = {}; + const arrayOptions = [ + 'array', 'boolean', 'string', 'skipValidation', + 'count', 'normalize', 'number', + 'hiddenOptions' + ]; + const objectOptions = [ + 'narg', 'key', 'alias', 'default', 'defaultDescription', + 'config', 'choices', 'demandedOptions', 'demandedCommands', 'coerce', + 'deprecatedOptions' + ]; + arrayOptions.forEach(k => { + tmpOptions[k] = (options[k] || []).filter(k => !localLookup[k]); + }); + objectOptions.forEach((k) => { + tmpOptions[k] = obj_filter_1.objFilter(options[k], k => !localLookup[k]); + }); + tmpOptions.envPrefix = options.envPrefix; + options = tmpOptions; + // if this is the first time being executed, create + // instances of all our helpers -- otherwise just reset. + usage = usage ? usage.reset(localLookup) : usage_1.usage(self, y18n); + validation = validation ? validation.reset(localLookup) : validation_1.validation(self, usage, y18n); + command = command ? command.reset() : command_1.command(self, usage, validation, globalMiddleware); + if (!completion) + completion = completion_1.completion(self, usage, command); + completionCommand = null; + output = ''; + exitError = null; + hasOutput = false; + self.parsed = false; + return self; + }; + self.resetOptions(); + // temporary hack: allow "freezing" of reset-able state for parse(msg, cb) + const frozens = []; + function freeze() { + frozens.push({ + options, + configObjects: options.configObjects.slice(0), + exitProcess, + groups, + strict, + strictCommands, + completionCommand, + output, + exitError, + hasOutput, + parsed: self.parsed, + parseFn, + parseContext, + handlerFinishCommand + }); + usage.freeze(); + validation.freeze(); + command.freeze(); + } + function unfreeze() { + const frozen = frozens.pop(); + common_types_1.assertNotStrictEqual(frozen, undefined); + let configObjects; + ({ + options, + configObjects, + exitProcess, + groups, + output, + exitError, + hasOutput, + parsed: self.parsed, + strict, + strictCommands, + completionCommand, + parseFn, + parseContext, + handlerFinishCommand + } = frozen); + options.configObjects = configObjects; + usage.unfreeze(); + validation.unfreeze(); + command.unfreeze(); + } + self.boolean = function (keys) { + argsert_1.argsert('', [keys], arguments.length); + populateParserHintArray('boolean', keys); + return self; + }; + self.array = function (keys) { + argsert_1.argsert('', [keys], arguments.length); + populateParserHintArray('array', keys); + return self; + }; + self.number = function (keys) { + argsert_1.argsert('', [keys], arguments.length); + populateParserHintArray('number', keys); + return self; + }; + self.normalize = function (keys) { + argsert_1.argsert('', [keys], arguments.length); + populateParserHintArray('normalize', keys); + return self; + }; + self.count = function (keys) { + argsert_1.argsert('', [keys], arguments.length); + populateParserHintArray('count', keys); + return self; + }; + self.string = function (keys) { + argsert_1.argsert('', [keys], arguments.length); + populateParserHintArray('string', keys); + return self; + }; + self.requiresArg = function (keys) { + // the 2nd paramter [number] in the argsert the assertion is mandatory + // as populateParserHintSingleValueDictionary recursively calls requiresArg + // with Nan as a 2nd parameter, although we ignore it + argsert_1.argsert(' [number]', [keys], arguments.length); + // If someone configures nargs at the same time as requiresArg, + // nargs should take precedent, + // see: https://github.com/yargs/yargs/pull/1572 + // TODO: make this work with aliases, using a check similar to + // checkAllAliases() in yargs-parser. + if (typeof keys === 'string' && options.narg[keys]) { + return self; + } + else { + populateParserHintSingleValueDictionary(self.requiresArg, 'narg', keys, NaN); + } + return self; + }; + self.skipValidation = function (keys) { + argsert_1.argsert('', [keys], arguments.length); + populateParserHintArray('skipValidation', keys); + return self; + }; + function populateParserHintArray(type, keys) { + keys = [].concat(keys); + keys.forEach((key) => { + key = sanitizeKey(key); + options[type].push(key); + }); + } + self.nargs = function (key, value) { + argsert_1.argsert(' [number]', [key, value], arguments.length); + populateParserHintSingleValueDictionary(self.nargs, 'narg', key, value); + return self; + }; + self.choices = function (key, value) { + argsert_1.argsert(' [string|array]', [key, value], arguments.length); + populateParserHintArrayDictionary(self.choices, 'choices', key, value); + return self; + }; + self.alias = function (key, value) { + argsert_1.argsert(' [string|array]', [key, value], arguments.length); + populateParserHintArrayDictionary(self.alias, 'alias', key, value); + return self; + }; + // TODO: actually deprecate self.defaults. + self.default = self.defaults = function (key, value, defaultDescription) { + argsert_1.argsert(' [*] [string]', [key, value, defaultDescription], arguments.length); + if (defaultDescription) { + common_types_1.assertSingleKey(key); + options.defaultDescription[key] = defaultDescription; + } + if (typeof value === 'function') { + common_types_1.assertSingleKey(key); + if (!options.defaultDescription[key]) + options.defaultDescription[key] = usage.functionDescription(value); + value = value.call(); + } + populateParserHintSingleValueDictionary(self.default, 'default', key, value); + return self; + }; + self.describe = function (key, desc) { + argsert_1.argsert(' [string]', [key, desc], arguments.length); + setKey(key, true); + usage.describe(key, desc); + return self; + }; + function setKey(key, set) { + populateParserHintSingleValueDictionary(setKey, 'key', key, set); + return self; + } + function demandOption(keys, msg) { + argsert_1.argsert(' [string]', [keys, msg], arguments.length); + populateParserHintSingleValueDictionary(self.demandOption, 'demandedOptions', keys, msg); + return self; + } + self.demandOption = demandOption; + self.coerce = function (keys, value) { + argsert_1.argsert(' [function]', [keys, value], arguments.length); + populateParserHintSingleValueDictionary(self.coerce, 'coerce', keys, value); + return self; + }; + function populateParserHintSingleValueDictionary(builder, type, key, value) { + populateParserHintDictionary(builder, type, key, value, (type, key, value) => { + options[type][key] = value; + }); + } + function populateParserHintArrayDictionary(builder, type, key, value) { + populateParserHintDictionary(builder, type, key, value, (type, key, value) => { + options[type][key] = (options[type][key] || []).concat(value); + }); + } + function populateParserHintDictionary(builder, type, key, value, singleKeyHandler) { + if (Array.isArray(key)) { + // an array of keys with one value ['x', 'y', 'z'], function parse () {} + key.forEach((k) => { + builder(k, value); + }); + } + else if (((key) => typeof key === 'object')(key)) { + // an object of key value pairs: {'x': parse () {}, 'y': parse() {}} + for (const k of common_types_1.objectKeys(key)) { + builder(k, key[k]); + } + } + else { + singleKeyHandler(type, sanitizeKey(key), value); + } + } + function sanitizeKey(key) { + if (key === '__proto__') + return '___proto___'; + return key; + } + function deleteFromParserHintObject(optionKey) { + // delete from all parsing hints: + // boolean, array, key, alias, etc. + common_types_1.objectKeys(options).forEach((hintKey) => { + // configObjects is not a parsing hint array + if (((key) => key === 'configObjects')(hintKey)) + return; + const hint = options[hintKey]; + if (Array.isArray(hint)) { + if (~hint.indexOf(optionKey)) + hint.splice(hint.indexOf(optionKey), 1); + } + else if (typeof hint === 'object') { + delete hint[optionKey]; + } + }); + // now delete the description from usage.js. + delete usage.getDescriptions()[optionKey]; + } + self.config = function config(key = 'config', msg, parseFn) { + argsert_1.argsert('[object|string] [string|function] [function]', [key, msg, parseFn], arguments.length); + // allow a config object to be provided directly. + if ((typeof key === 'object') && !Array.isArray(key)) { + key = apply_extends_1.applyExtends(key, cwd, self.getParserConfiguration()['deep-merge-config']); + options.configObjects = (options.configObjects || []).concat(key); + return self; + } + // allow for a custom parsing function. + if (typeof msg === 'function') { + parseFn = msg; + msg = undefined; + } + self.describe(key, msg || usage.deferY18nLookup('Path to JSON config file')); + (Array.isArray(key) ? key : [key]).forEach((k) => { + options.config[k] = parseFn || true; + }); + return self; + }; + self.example = function (cmd, description) { + argsert_1.argsert(' [string]', [cmd, description], arguments.length); + if (Array.isArray(cmd)) { + cmd.forEach((exampleParams) => self.example(...exampleParams)); + } + else { + usage.example(cmd, description); + } + return self; + }; + self.command = function (cmd, description, builder, handler, middlewares, deprecated) { + argsert_1.argsert(' [string|boolean] [function|object] [function] [array] [boolean|string]', [cmd, description, builder, handler, middlewares, deprecated], arguments.length); + command.addHandler(cmd, description, builder, handler, middlewares, deprecated); + return self; + }; + self.commandDir = function (dir, opts) { + argsert_1.argsert(' [object]', [dir, opts], arguments.length); + const req = parentRequire || require; + command.addDirectory(dir, self.getContext(), req, require('get-caller-file')(), opts); + return self; + }; + // TODO: deprecate self.demand in favor of + // .demandCommand() .demandOption(). + self.demand = self.required = self.require = function demand(keys, max, msg) { + // you can optionally provide a 'max' key, + // which will raise an exception if too many '_' + // options are provided. + if (Array.isArray(max)) { + max.forEach((key) => { + common_types_1.assertNotStrictEqual(msg, true); + demandOption(key, msg); + }); + max = Infinity; + } + else if (typeof max !== 'number') { + msg = max; + max = Infinity; + } + if (typeof keys === 'number') { + common_types_1.assertNotStrictEqual(msg, true); + self.demandCommand(keys, max, msg, msg); + } + else if (Array.isArray(keys)) { + keys.forEach((key) => { + common_types_1.assertNotStrictEqual(msg, true); + demandOption(key, msg); + }); + } + else { + if (typeof msg === 'string') { + demandOption(keys, msg); + } + else if (msg === true || typeof msg === 'undefined') { + demandOption(keys); + } + } + return self; + }; + self.demandCommand = function demandCommand(min = 1, max, minMsg, maxMsg) { + argsert_1.argsert('[number] [number|string] [string|null|undefined] [string|null|undefined]', [min, max, minMsg, maxMsg], arguments.length); + if (typeof max !== 'number') { + minMsg = max; + max = Infinity; + } + self.global('_', false); + options.demandedCommands._ = { + min, + max, + minMsg, + maxMsg + }; + return self; + }; + self.getDemandedOptions = () => { + argsert_1.argsert([], 0); + return options.demandedOptions; + }; + self.getDemandedCommands = () => { + argsert_1.argsert([], 0); + return options.demandedCommands; + }; + self.deprecateOption = function deprecateOption(option, message) { + argsert_1.argsert(' [string|boolean]', [option, message], arguments.length); + options.deprecatedOptions[option] = message; + return self; + }; + self.getDeprecatedOptions = () => { + argsert_1.argsert([], 0); + return options.deprecatedOptions; + }; + self.implies = function (key, value) { + argsert_1.argsert(' [number|string|array]', [key, value], arguments.length); + validation.implies(key, value); + return self; + }; + self.conflicts = function (key1, key2) { + argsert_1.argsert(' [string|array]', [key1, key2], arguments.length); + validation.conflicts(key1, key2); + return self; + }; + self.usage = function (msg, description, builder, handler) { + argsert_1.argsert(' [string|boolean] [function|object] [function]', [msg, description, builder, handler], arguments.length); + if (description !== undefined) { + common_types_1.assertNotStrictEqual(msg, null); + // .usage() can be used as an alias for defining + // a default command. + if ((msg || '').match(/^\$0( |$)/)) { + return self.command(msg, description, builder, handler); + } + else { + throw new yerror_1.YError('.usage() description must start with $0 if being used as alias for .command()'); + } + } + else { + usage.usage(msg); + return self; + } + }; + self.epilogue = self.epilog = function (msg) { + argsert_1.argsert('', [msg], arguments.length); + usage.epilog(msg); + return self; + }; + self.fail = function (f) { + argsert_1.argsert('', [f], arguments.length); + usage.failFn(f); + return self; + }; + self.onFinishCommand = function (f) { + argsert_1.argsert('', [f], arguments.length); + handlerFinishCommand = f; + return self; + }; + self.getHandlerFinishCommand = () => handlerFinishCommand; + self.check = function (f, _global) { + argsert_1.argsert(' [boolean]', [f, _global], arguments.length); + validation.check(f, _global !== false); + return self; + }; + self.global = function global(globals, global) { + argsert_1.argsert(' [boolean]', [globals, global], arguments.length); + globals = [].concat(globals); + if (global !== false) { + options.local = options.local.filter(l => globals.indexOf(l) === -1); + } + else { + globals.forEach((g) => { + if (options.local.indexOf(g) === -1) + options.local.push(g); + }); + } + return self; + }; + self.pkgConf = function pkgConf(key, rootPath) { + argsert_1.argsert(' [string]', [key, rootPath], arguments.length); + let conf = null; + // prefer cwd to require-main-filename in this method + // since we're looking for e.g. "nyc" config in nyc consumer + // rather than "yargs" config in nyc (where nyc is the main filename) + const obj = pkgUp(rootPath || cwd); + // If an object exists in the key, add it to options.configObjects + if (obj[key] && typeof obj[key] === 'object') { + conf = apply_extends_1.applyExtends(obj[key], rootPath || cwd, self.getParserConfiguration()['deep-merge-config']); + options.configObjects = (options.configObjects || []).concat(conf); + } + return self; + }; + const pkgs = {}; + function pkgUp(rootPath) { + const npath = rootPath || '*'; + if (pkgs[npath]) + return pkgs[npath]; + let obj = {}; + try { + let startDir = rootPath || requireMainFilename(parentRequire); + // When called in an environment that lacks require.main.filename, such as a jest test runner, + // startDir is already process.cwd(), and should not be shortened. + // Whether or not it is _actually_ a directory (e.g., extensionless bin) is irrelevant, find-up handles it. + if (!rootPath && path.extname(startDir)) { + startDir = path.dirname(startDir); + } + const pkgJsonPath = findUp.sync('package.json', { + cwd: startDir + }); + common_types_1.assertNotStrictEqual(pkgJsonPath, undefined); + obj = JSON.parse(fs.readFileSync(pkgJsonPath).toString()); + } + catch (noop) { } + pkgs[npath] = obj || {}; + return pkgs[npath]; + } + let parseFn = null; + let parseContext = null; + self.parse = function parse(args, shortCircuit, _parseFn) { + argsert_1.argsert('[string|array] [function|boolean|object] [function]', [args, shortCircuit, _parseFn], arguments.length); + freeze(); + if (typeof args === 'undefined') { + const argv = self._parseArgs(processArgs); + const tmpParsed = self.parsed; + unfreeze(); + // TODO: remove this compatibility hack when we release yargs@15.x: + self.parsed = tmpParsed; + return argv; + } + // a context object can optionally be provided, this allows + // additional information to be passed to a command handler. + if (typeof shortCircuit === 'object') { + parseContext = shortCircuit; + shortCircuit = _parseFn; + } + // by providing a function as a second argument to + // parse you can capture output that would otherwise + // default to printing to stdout/stderr. + if (typeof shortCircuit === 'function') { + parseFn = shortCircuit; + shortCircuit = false; + } + // completion short-circuits the parsing process, + // skipping validation, etc. + if (!shortCircuit) + processArgs = args; + if (parseFn) + exitProcess = false; + const parsed = self._parseArgs(args, !!shortCircuit); + completion.setParsed(self.parsed); + if (parseFn) + parseFn(exitError, parsed, output); + unfreeze(); + return parsed; + }; + self._getParseContext = () => parseContext || {}; + self._hasParseCallback = () => !!parseFn; + self.option = self.options = function option(key, opt) { + argsert_1.argsert(' [object]', [key, opt], arguments.length); + if (typeof key === 'object') { + Object.keys(key).forEach((k) => { + self.options(k, key[k]); + }); + } + else { + if (typeof opt !== 'object') { + opt = {}; + } + options.key[key] = true; // track manually set keys. + if (opt.alias) + self.alias(key, opt.alias); + const deprecate = opt.deprecate || opt.deprecated; + if (deprecate) { + self.deprecateOption(key, deprecate); + } + const demand = opt.demand || opt.required || opt.require; + // A required option can be specified via "demand: true". + if (demand) { + self.demand(key, demand); + } + if (opt.demandOption) { + self.demandOption(key, typeof opt.demandOption === 'string' ? opt.demandOption : undefined); + } + if (opt.conflicts) { + self.conflicts(key, opt.conflicts); + } + if ('default' in opt) { + self.default(key, opt.default); + } + if (opt.implies !== undefined) { + self.implies(key, opt.implies); + } + if (opt.nargs !== undefined) { + self.nargs(key, opt.nargs); + } + if (opt.config) { + self.config(key, opt.configParser); + } + if (opt.normalize) { + self.normalize(key); + } + if (opt.choices) { + self.choices(key, opt.choices); + } + if (opt.coerce) { + self.coerce(key, opt.coerce); + } + if (opt.group) { + self.group(key, opt.group); + } + if (opt.boolean || opt.type === 'boolean') { + self.boolean(key); + if (opt.alias) + self.boolean(opt.alias); + } + if (opt.array || opt.type === 'array') { + self.array(key); + if (opt.alias) + self.array(opt.alias); + } + if (opt.number || opt.type === 'number') { + self.number(key); + if (opt.alias) + self.number(opt.alias); + } + if (opt.string || opt.type === 'string') { + self.string(key); + if (opt.alias) + self.string(opt.alias); + } + if (opt.count || opt.type === 'count') { + self.count(key); + } + if (typeof opt.global === 'boolean') { + self.global(key, opt.global); + } + if (opt.defaultDescription) { + options.defaultDescription[key] = opt.defaultDescription; + } + if (opt.skipValidation) { + self.skipValidation(key); + } + const desc = opt.describe || opt.description || opt.desc; + self.describe(key, desc); + if (opt.hidden) { + self.hide(key); + } + if (opt.requiresArg) { + self.requiresArg(key); + } + } + return self; + }; + self.getOptions = () => options; + self.positional = function (key, opts) { + argsert_1.argsert(' ', [key, opts], arguments.length); + if (context.resets === 0) { + throw new yerror_1.YError(".positional() can only be called in a command's builder function"); + } + // .positional() only supports a subset of the configuration + // options available to .option(). + const supportedOpts = ['default', 'defaultDescription', 'implies', 'normalize', + 'choices', 'conflicts', 'coerce', 'type', 'describe', + 'desc', 'description', 'alias']; + opts = obj_filter_1.objFilter(opts, (k, v) => { + let accept = supportedOpts.indexOf(k) !== -1; + // type can be one of string|number|boolean. + if (k === 'type' && ['string', 'number', 'boolean'].indexOf(v) === -1) + accept = false; + return accept; + }); + // copy over any settings that can be inferred from the command string. + const fullCommand = context.fullCommands[context.fullCommands.length - 1]; + const parseOptions = fullCommand ? command.cmdToParseOptions(fullCommand) : { + array: [], + alias: {}, + default: {}, + demand: {} + }; + common_types_1.objectKeys(parseOptions).forEach((pk) => { + const parseOption = parseOptions[pk]; + if (Array.isArray(parseOption)) { + if (parseOption.indexOf(key) !== -1) + opts[pk] = true; + } + else { + if (parseOption[key] && !(pk in opts)) + opts[pk] = parseOption[key]; + } + }); + self.group(key, usage.getPositionalGroupName()); + return self.option(key, opts); + }; + self.group = function group(opts, groupName) { + argsert_1.argsert(' ', [opts, groupName], arguments.length); + const existing = preservedGroups[groupName] || groups[groupName]; + if (preservedGroups[groupName]) { + // we now only need to track this group name in groups. + delete preservedGroups[groupName]; + } + const seen = {}; + groups[groupName] = (existing || []).concat(opts).filter((key) => { + if (seen[key]) + return false; + return (seen[key] = true); + }); + return self; + }; + // combine explicit and preserved groups. explicit groups should be first + self.getGroups = () => Object.assign({}, groups, preservedGroups); + // as long as options.envPrefix is not undefined, + // parser will apply env vars matching prefix to argv + self.env = function (prefix) { + argsert_1.argsert('[string|boolean]', [prefix], arguments.length); + if (prefix === false) + delete options.envPrefix; + else + options.envPrefix = prefix || ''; + return self; + }; + self.wrap = function (cols) { + argsert_1.argsert('', [cols], arguments.length); + usage.wrap(cols); + return self; + }; + let strict = false; + self.strict = function (enabled) { + argsert_1.argsert('[boolean]', [enabled], arguments.length); + strict = enabled !== false; + return self; + }; + self.getStrict = () => strict; + let strictCommands = false; + self.strictCommands = function (enabled) { + argsert_1.argsert('[boolean]', [enabled], arguments.length); + strictCommands = enabled !== false; + return self; + }; + self.getStrictCommands = () => strictCommands; + let parserConfig = {}; + self.parserConfiguration = function parserConfiguration(config) { + argsert_1.argsert('', [config], arguments.length); + parserConfig = config; + return self; + }; + self.getParserConfiguration = () => parserConfig; + self.showHelp = function (level) { + argsert_1.argsert('[string|function]', [level], arguments.length); + if (!self.parsed) + self._parseArgs(processArgs); // run parser, if it has not already been executed. + if (command.hasDefaultCommand()) { + context.resets++; // override the restriction on top-level positoinals. + command.runDefaultBuilderOn(self); + } + usage.showHelp(level); + return self; + }; + let versionOpt = null; + self.version = function version(opt, msg, ver) { + const defaultVersionOpt = 'version'; + argsert_1.argsert('[boolean|string] [string] [string]', [opt, msg, ver], arguments.length); + // nuke the key previously configured + // to return version #. + if (versionOpt) { + deleteFromParserHintObject(versionOpt); + usage.version(undefined); + versionOpt = null; + } + if (arguments.length === 0) { + ver = guessVersion(); + opt = defaultVersionOpt; + } + else if (arguments.length === 1) { + if (opt === false) { // disable default 'version' key. + return self; + } + ver = opt; + opt = defaultVersionOpt; + } + else if (arguments.length === 2) { + ver = msg; + msg = undefined; + } + versionOpt = typeof opt === 'string' ? opt : defaultVersionOpt; + msg = msg || usage.deferY18nLookup('Show version number'); + usage.version(ver || undefined); + self.boolean(versionOpt); + self.describe(versionOpt, msg); + return self; + }; + function guessVersion() { + const obj = pkgUp(); + return obj.version || 'unknown'; + } + let helpOpt = null; + self.addHelpOpt = self.help = function addHelpOpt(opt, msg) { + const defaultHelpOpt = 'help'; + argsert_1.argsert('[string|boolean] [string]', [opt, msg], arguments.length); + // nuke the key previously configured + // to return help. + if (helpOpt) { + deleteFromParserHintObject(helpOpt); + helpOpt = null; + } + if (arguments.length === 1) { + if (opt === false) + return self; + } + // use arguments, fallback to defaults for opt and msg + helpOpt = typeof opt === 'string' ? opt : defaultHelpOpt; + self.boolean(helpOpt); + self.describe(helpOpt, msg || usage.deferY18nLookup('Show help')); + return self; + }; + const defaultShowHiddenOpt = 'show-hidden'; + options.showHiddenOpt = defaultShowHiddenOpt; + self.addShowHiddenOpt = self.showHidden = function addShowHiddenOpt(opt, msg) { + argsert_1.argsert('[string|boolean] [string]', [opt, msg], arguments.length); + if (arguments.length === 1) { + if (opt === false) + return self; + } + const showHiddenOpt = typeof opt === 'string' ? opt : defaultShowHiddenOpt; + self.boolean(showHiddenOpt); + self.describe(showHiddenOpt, msg || usage.deferY18nLookup('Show hidden options')); + options.showHiddenOpt = showHiddenOpt; + return self; + }; + self.hide = function hide(key) { + argsert_1.argsert('', [key], arguments.length); + options.hiddenOptions.push(key); + return self; + }; + self.showHelpOnFail = function showHelpOnFail(enabled, message) { + argsert_1.argsert('[boolean|string] [string]', [enabled, message], arguments.length); + usage.showHelpOnFail(enabled, message); + return self; + }; + var exitProcess = true; + self.exitProcess = function (enabled = true) { + argsert_1.argsert('[boolean]', [enabled], arguments.length); + exitProcess = enabled; + return self; + }; + self.getExitProcess = () => exitProcess; + var completionCommand = null; + self.completion = function (cmd, desc, fn) { + argsert_1.argsert('[string] [string|boolean|function] [function]', [cmd, desc, fn], arguments.length); + // a function to execute when generating + // completions can be provided as the second + // or third argument to completion. + if (typeof desc === 'function') { + fn = desc; + desc = undefined; + } + // register the completion command. + completionCommand = cmd || completionCommand || 'completion'; + if (!desc && desc !== false) { + desc = 'generate completion script'; + } + self.command(completionCommand, desc); + // a function can be provided + if (fn) + completion.registerFunction(fn); + return self; + }; + self.showCompletionScript = function ($0, cmd) { + argsert_1.argsert('[string] [string]', [$0, cmd], arguments.length); + $0 = $0 || self.$0; + _logger.log(completion.generateCompletionScript($0, cmd || completionCommand || 'completion')); + return self; + }; + self.getCompletion = function (args, done) { + argsert_1.argsert(' ', [args, done], arguments.length); + completion.getCompletion(args, done); + }; + self.locale = function (locale) { + argsert_1.argsert('[string]', [locale], arguments.length); + if (!locale) { + guessLocale(); + return y18n.getLocale(); + } + detectLocale = false; + y18n.setLocale(locale); + return self; + }; + self.updateStrings = self.updateLocale = function (obj) { + argsert_1.argsert('', [obj], arguments.length); + detectLocale = false; + y18n.updateLocale(obj); + return self; + }; + let detectLocale = true; + self.detectLocale = function (detect) { + argsert_1.argsert('', [detect], arguments.length); + detectLocale = detect; + return self; + }; + self.getDetectLocale = () => detectLocale; + var hasOutput = false; + var exitError = null; + // maybe exit, always capture + // context about why we wanted to exit. + self.exit = (code, err) => { + hasOutput = true; + exitError = err; + if (exitProcess) + process.exit(code); + }; + // we use a custom logger that buffers output, + // so that we can print to non-CLIs, e.g., chat-bots. + const _logger = { + log(...args) { + if (!self._hasParseCallback()) + console.log(...args); + hasOutput = true; + if (output.length) + output += '\n'; + output += args.join(' '); + }, + error(...args) { + if (!self._hasParseCallback()) + console.error(...args); + hasOutput = true; + if (output.length) + output += '\n'; + output += args.join(' '); + } + }; + self._getLoggerInstance = () => _logger; + // has yargs output an error our help + // message in the current execution context. + self._hasOutput = () => hasOutput; + self._setHasOutput = () => { + hasOutput = true; + }; + let recommendCommands; + self.recommendCommands = function (recommend = true) { + argsert_1.argsert('[boolean]', [recommend], arguments.length); + recommendCommands = recommend; + return self; + }; + self.getUsageInstance = () => usage; + self.getValidationInstance = () => validation; + self.getCommandInstance = () => command; + self.terminalWidth = () => { + argsert_1.argsert([], 0); + return typeof process.stdout.columns !== 'undefined' ? process.stdout.columns : null; + }; + Object.defineProperty(self, 'argv', { + get: () => self._parseArgs(processArgs), + enumerable: true + }); + self._parseArgs = function parseArgs(args, shortCircuit, _calledFromCommand, commandIndex) { + let skipValidation = !!_calledFromCommand; + args = args || processArgs; + options.__ = y18n.__; + options.configuration = self.getParserConfiguration(); + const populateDoubleDash = !!options.configuration['populate--']; + const config = Object.assign({}, options.configuration, { + 'populate--': true + }); + const parsed = Parser.detailed(args, Object.assign({}, options, { + configuration: config + })); + let argv = parsed.argv; + if (parseContext) + argv = Object.assign({}, argv, parseContext); + const aliases = parsed.aliases; + argv.$0 = self.$0; + self.parsed = parsed; + try { + guessLocale(); // guess locale lazily, so that it can be turned off in chain. + // while building up the argv object, there + // are two passes through the parser. If completion + // is being performed short-circuit on the first pass. + if (shortCircuit) { + return (populateDoubleDash || _calledFromCommand) ? argv : self._copyDoubleDash(argv); + } + // if there's a handler associated with a + // command defer processing to it. + if (helpOpt) { + // consider any multi-char helpOpt alias as a valid help command + // unless all helpOpt aliases are single-char + // note that parsed.aliases is a normalized bidirectional map :) + const helpCmds = [helpOpt] + .concat(aliases[helpOpt] || []) + .filter(k => k.length > 1); + // check if help should trigger and strip it from _. + if (~helpCmds.indexOf(argv._[argv._.length - 1])) { + argv._.pop(); + argv[helpOpt] = true; + } + } + const handlerKeys = command.getCommands(); + const requestCompletions = completion.completionKey in argv; + const skipRecommendation = argv[helpOpt] || requestCompletions; + const skipDefaultCommand = skipRecommendation && (handlerKeys.length > 1 || handlerKeys[0] !== '$0'); + if (argv._.length) { + if (handlerKeys.length) { + let firstUnknownCommand; + for (let i = (commandIndex || 0), cmd; argv._[i] !== undefined; i++) { + cmd = String(argv._[i]); + if (~handlerKeys.indexOf(cmd) && cmd !== completionCommand) { + // commands are executed using a recursive algorithm that executes + // the deepest command first; we keep track of the position in the + // argv._ array that is currently being executed. + const innerArgv = command.runCommand(cmd, self, parsed, i + 1); + return populateDoubleDash ? innerArgv : self._copyDoubleDash(innerArgv); + } + else if (!firstUnknownCommand && cmd !== completionCommand) { + firstUnknownCommand = cmd; + break; + } + } + // run the default command, if defined + if (command.hasDefaultCommand() && !skipDefaultCommand) { + const innerArgv = command.runCommand(null, self, parsed); + return populateDoubleDash ? innerArgv : self._copyDoubleDash(innerArgv); + } + // recommend a command if recommendCommands() has + // been enabled, and no commands were found to execute + if (recommendCommands && firstUnknownCommand && !skipRecommendation) { + validation.recommendCommands(firstUnknownCommand, handlerKeys); + } + } + // generate a completion script for adding to ~/.bashrc. + if (completionCommand && ~argv._.indexOf(completionCommand) && !requestCompletions) { + if (exitProcess) + setBlocking(true); + self.showCompletionScript(); + self.exit(0); + } + } + else if (command.hasDefaultCommand() && !skipDefaultCommand) { + const innerArgv = command.runCommand(null, self, parsed); + return populateDoubleDash ? innerArgv : self._copyDoubleDash(innerArgv); + } + // we must run completions first, a user might + // want to complete the --help or --version option. + if (requestCompletions) { + if (exitProcess) + setBlocking(true); + // we allow for asynchronous completions, + // e.g., loading in a list of commands from an API. + args = [].concat(args); + const completionArgs = args.slice(args.indexOf(`--${completion.completionKey}`) + 1); + completion.getCompletion(completionArgs, (completions) => { + ; + (completions || []).forEach((completion) => { + _logger.log(completion); + }); + self.exit(0); + }); + return (populateDoubleDash || _calledFromCommand) ? argv : self._copyDoubleDash(argv); + } + // Handle 'help' and 'version' options + // if we haven't already output help! + if (!hasOutput) { + Object.keys(argv).forEach((key) => { + if (key === helpOpt && argv[key]) { + if (exitProcess) + setBlocking(true); + skipValidation = true; + self.showHelp('log'); + self.exit(0); + } + else if (key === versionOpt && argv[key]) { + if (exitProcess) + setBlocking(true); + skipValidation = true; + usage.showVersion(); + self.exit(0); + } + }); + } + // Check if any of the options to skip validation were provided + if (!skipValidation && options.skipValidation.length > 0) { + skipValidation = Object.keys(argv).some(key => options.skipValidation.indexOf(key) >= 0 && argv[key] === true); + } + // If the help or version options where used and exitProcess is false, + // or if explicitly skipped, we won't run validations. + if (!skipValidation) { + if (parsed.error) + throw new yerror_1.YError(parsed.error.message); + // if we're executed via bash completion, don't + // bother with validation. + if (!requestCompletions) { + self._runValidation(argv, aliases, {}, parsed.error); + } + } + } + catch (err) { + if (err instanceof yerror_1.YError) + usage.fail(err.message, err); + else + throw err; + } + return (populateDoubleDash || _calledFromCommand) ? argv : self._copyDoubleDash(argv); + }; + // to simplify the parsing of positionals in commands, + // we temporarily populate '--' rather than _, with arguments + // after the '--' directive. After the parse, we copy these back. + self._copyDoubleDash = function (argv) { + if (is_promise_1.isPromise(argv) || !argv._ || !argv['--']) + return argv; + argv._.push.apply(argv._, argv['--']); + // TODO(bcoe): refactor command parsing such that this delete is not + // necessary: https://github.com/yargs/yargs/issues/1482 + try { + delete argv['--']; + } + catch (_err) { } + return argv; + }; + self._runValidation = function runValidation(argv, aliases, positionalMap, parseErrors, isDefaultCommand = false) { + if (parseErrors) + throw new yerror_1.YError(parseErrors.message); + validation.nonOptionCount(argv); + validation.requiredArguments(argv); + let failedStrictCommands = false; + if (strictCommands) { + failedStrictCommands = validation.unknownCommands(argv); + } + if (strict && !failedStrictCommands) { + validation.unknownArguments(argv, aliases, positionalMap, isDefaultCommand); + } + validation.customChecks(argv, aliases); + validation.limitedChoices(argv); + validation.implications(argv); + validation.conflicting(argv); + }; + function guessLocale() { + if (!detectLocale) + return; + const locale = process.env.LC_ALL || process.env.LC_MESSAGES || process.env.LANG || process.env.LANGUAGE || 'en_US'; + self.locale(locale.replace(/[.:].*/, '')); + } + // an app should almost always have --version and --help, + // if you *really* want to disable this use .help(false)/.version(false). + self.help(); + self.version(); + return self; +} +exports.Yargs = Yargs; +// rebase an absolute path to a relative one with respect to a base directory +// exported for tests +function rebase(base, dir) { + return path.relative(base, dir); +} +exports.rebase = rebase; +function isYargsInstance(y) { + return !!y && (typeof y._parseArgs === 'function'); +} +exports.isYargsInstance = isYargsInstance; diff --git a/node_modules/yargs/build/lib/yerror.d.ts b/node_modules/yargs/build/lib/yerror.d.ts new file mode 100644 index 0000000..024d0c7 --- /dev/null +++ b/node_modules/yargs/build/lib/yerror.d.ts @@ -0,0 +1,4 @@ +export declare class YError extends Error { + name: string; + constructor(msg?: string | null); +} diff --git a/node_modules/yargs/build/lib/yerror.js b/node_modules/yargs/build/lib/yerror.js new file mode 100644 index 0000000..0fa146e --- /dev/null +++ b/node_modules/yargs/build/lib/yerror.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.YError = void 0; +class YError extends Error { + constructor(msg) { + super(msg || 'yargs error'); + this.name = 'YError'; + Error.captureStackTrace(this, YError); + } +} +exports.YError = YError; diff --git a/node_modules/yargs/index.js b/node_modules/yargs/index.js new file mode 100644 index 0000000..7dc62de --- /dev/null +++ b/node_modules/yargs/index.js @@ -0,0 +1,40 @@ +'use strict' +// classic singleton yargs API, to use yargs +// without running as a singleton do: +// require('yargs/yargs')(process.argv.slice(2)) +const yargs = require('./yargs') +const processArgv = require('./build/lib/process-argv') + +Argv(processArgv.getProcessArgvWithoutBin()) + +module.exports = Argv + +function Argv (processArgs, cwd) { + const argv = yargs(processArgs, cwd, require) + singletonify(argv) + return argv +} + +/* Hack an instance of Argv with process.argv into Argv + so people can do + require('yargs')(['--beeble=1','-z','zizzle']).argv + to parse a list of args and + require('yargs').argv + to get a parsed version of process.argv. +*/ +function singletonify (inst) { + Object.keys(inst).forEach((key) => { + if (key === 'argv') { + Argv.__defineGetter__(key, inst.__lookupGetter__(key)) + } else if (typeof inst[key] === 'function') { + Argv[key] = inst[key].bind(inst) + } else { + Argv.__defineGetter__('$0', () => { + return inst.$0 + }) + Argv.__defineGetter__('parsed', () => { + return inst.parsed + }) + } + }) +} diff --git a/node_modules/yargs/locales/be.json b/node_modules/yargs/locales/be.json new file mode 100644 index 0000000..e28fa30 --- /dev/null +++ b/node_modules/yargs/locales/be.json @@ -0,0 +1,46 @@ +{ + "Commands:": "Каманды:", + "Options:": "Опцыі:", + "Examples:": "Прыклады:", + "boolean": "булевы тып", + "count": "падлік", + "string": "радковы тып", + "number": "лік", + "array": "масіў", + "required": "неабходна", + "default": "па змаўчанні", + "default:": "па змаўчанні:", + "choices:": "магчымасці:", + "aliases:": "аліасы:", + "generated-value": "згенераванае значэнне", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Недастаткова неапцыйных аргументаў: ёсць %s, трэба як мінімум %s", + "other": "Недастаткова неапцыйных аргументаў: ёсць %s, трэба як мінімум %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Занадта шмат неапцыйных аргументаў: ёсць %s, максімум дапушчальна %s", + "other": "Занадта шмат неапцыйных аргументаў: ёсць %s, максімум дапушчальна %s" + }, + "Missing argument value: %s": { + "one": "Не хапае значэння аргументу: %s", + "other": "Не хапае значэнняў аргументаў: %s" + }, + "Missing required argument: %s": { + "one": "Не хапае неабходнага аргументу: %s", + "other": "Не хапае неабходных аргументаў: %s" + }, + "Unknown argument: %s": { + "one": "Невядомы аргумент: %s", + "other": "Невядомыя аргументы: %s" + }, + "Invalid values:": "Несапраўдныя значэння:", + "Argument: %s, Given: %s, Choices: %s": "Аргумент: %s, Дадзенае значэнне: %s, Магчымасці: %s", + "Argument check failed: %s": "Праверка аргументаў не ўдалася: %s", + "Implications failed:": "Дадзены аргумент патрабуе наступны дадатковы аргумент:", + "Not enough arguments following: %s": "Недастаткова наступных аргументаў: %s", + "Invalid JSON config file: %s": "Несапраўдны файл канфігурацыі JSON: %s", + "Path to JSON config file": "Шлях да файла канфігурацыі JSON", + "Show help": "Паказаць дапамогу", + "Show version number": "Паказаць нумар версіі", + "Did you mean %s?": "Вы мелі на ўвазе %s?" +} diff --git a/node_modules/yargs/locales/de.json b/node_modules/yargs/locales/de.json new file mode 100644 index 0000000..dc73ec3 --- /dev/null +++ b/node_modules/yargs/locales/de.json @@ -0,0 +1,46 @@ +{ + "Commands:": "Kommandos:", + "Options:": "Optionen:", + "Examples:": "Beispiele:", + "boolean": "boolean", + "count": "Zähler", + "string": "string", + "number": "Zahl", + "array": "array", + "required": "erforderlich", + "default": "Standard", + "default:": "Standard:", + "choices:": "Möglichkeiten:", + "aliases:": "Aliase:", + "generated-value": "Generierter-Wert", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Nicht genügend Argumente ohne Optionen: %s vorhanden, mindestens %s benötigt", + "other": "Nicht genügend Argumente ohne Optionen: %s vorhanden, mindestens %s benötigt" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Zu viele Argumente ohne Optionen: %s vorhanden, maximal %s erlaubt", + "other": "Zu viele Argumente ohne Optionen: %s vorhanden, maximal %s erlaubt" + }, + "Missing argument value: %s": { + "one": "Fehlender Argumentwert: %s", + "other": "Fehlende Argumentwerte: %s" + }, + "Missing required argument: %s": { + "one": "Fehlendes Argument: %s", + "other": "Fehlende Argumente: %s" + }, + "Unknown argument: %s": { + "one": "Unbekanntes Argument: %s", + "other": "Unbekannte Argumente: %s" + }, + "Invalid values:": "Unzulässige Werte:", + "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Gegeben: %s, Möglichkeiten: %s", + "Argument check failed: %s": "Argumente-Check fehlgeschlagen: %s", + "Implications failed:": "Fehlende abhängige Argumente:", + "Not enough arguments following: %s": "Nicht genügend Argumente nach: %s", + "Invalid JSON config file: %s": "Fehlerhafte JSON-Config Datei: %s", + "Path to JSON config file": "Pfad zur JSON-Config Datei", + "Show help": "Hilfe anzeigen", + "Show version number": "Version anzeigen", + "Did you mean %s?": "Meintest du %s?" +} diff --git a/node_modules/yargs/locales/en.json b/node_modules/yargs/locales/en.json new file mode 100644 index 0000000..d794947 --- /dev/null +++ b/node_modules/yargs/locales/en.json @@ -0,0 +1,51 @@ +{ + "Commands:": "Commands:", + "Options:": "Options:", + "Examples:": "Examples:", + "boolean": "boolean", + "count": "count", + "string": "string", + "number": "number", + "array": "array", + "required": "required", + "default": "default", + "default:": "default:", + "choices:": "choices:", + "aliases:": "aliases:", + "generated-value": "generated-value", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Not enough non-option arguments: got %s, need at least %s", + "other": "Not enough non-option arguments: got %s, need at least %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Too many non-option arguments: got %s, maximum of %s", + "other": "Too many non-option arguments: got %s, maximum of %s" + }, + "Missing argument value: %s": { + "one": "Missing argument value: %s", + "other": "Missing argument values: %s" + }, + "Missing required argument: %s": { + "one": "Missing required argument: %s", + "other": "Missing required arguments: %s" + }, + "Unknown argument: %s": { + "one": "Unknown argument: %s", + "other": "Unknown arguments: %s" + }, + "Invalid values:": "Invalid values:", + "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Given: %s, Choices: %s", + "Argument check failed: %s": "Argument check failed: %s", + "Implications failed:": "Missing dependent arguments:", + "Not enough arguments following: %s": "Not enough arguments following: %s", + "Invalid JSON config file: %s": "Invalid JSON config file: %s", + "Path to JSON config file": "Path to JSON config file", + "Show help": "Show help", + "Show version number": "Show version number", + "Did you mean %s?": "Did you mean %s?", + "Arguments %s and %s are mutually exclusive" : "Arguments %s and %s are mutually exclusive", + "Positionals:": "Positionals:", + "command": "command", + "deprecated": "deprecated", + "deprecated: %s": "deprecated: %s" +} diff --git a/node_modules/yargs/locales/es.json b/node_modules/yargs/locales/es.json new file mode 100644 index 0000000..d77b461 --- /dev/null +++ b/node_modules/yargs/locales/es.json @@ -0,0 +1,46 @@ +{ + "Commands:": "Comandos:", + "Options:": "Opciones:", + "Examples:": "Ejemplos:", + "boolean": "booleano", + "count": "cuenta", + "string": "cadena de caracteres", + "number": "número", + "array": "tabla", + "required": "requerido", + "default": "defecto", + "default:": "defecto:", + "choices:": "selección:", + "aliases:": "alias:", + "generated-value": "valor-generado", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Hacen falta argumentos no-opcionales: Número recibido %s, necesita por lo menos %s", + "other": "Hacen falta argumentos no-opcionales: Número recibido %s, necesita por lo menos %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Demasiados argumentos no-opcionales: Número recibido %s, máximo es %s", + "other": "Demasiados argumentos no-opcionales: Número recibido %s, máximo es %s" + }, + "Missing argument value: %s": { + "one": "Falta argumento: %s", + "other": "Faltan argumentos: %s" + }, + "Missing required argument: %s": { + "one": "Falta argumento requerido: %s", + "other": "Faltan argumentos requeridos: %s" + }, + "Unknown argument: %s": { + "one": "Argumento desconocido: %s", + "other": "Argumentos desconocidos: %s" + }, + "Invalid values:": "Valores inválidos:", + "Argument: %s, Given: %s, Choices: %s": "Argumento: %s, Recibido: %s, Seleccionados: %s", + "Argument check failed: %s": "Verificación de argumento ha fallado: %s", + "Implications failed:": "Implicaciones fallidas:", + "Not enough arguments following: %s": "No hay suficientes argumentos después de: %s", + "Invalid JSON config file: %s": "Archivo de configuración JSON inválido: %s", + "Path to JSON config file": "Ruta al archivo de configuración JSON", + "Show help": "Muestra ayuda", + "Show version number": "Muestra número de versión", + "Did you mean %s?": "Quisiste decir %s?" +} diff --git a/node_modules/yargs/locales/fi.json b/node_modules/yargs/locales/fi.json new file mode 100644 index 0000000..0728c57 --- /dev/null +++ b/node_modules/yargs/locales/fi.json @@ -0,0 +1,49 @@ +{ + "Commands:": "Komennot:", + "Options:": "Valinnat:", + "Examples:": "Esimerkkejä:", + "boolean": "totuusarvo", + "count": "lukumäärä", + "string": "merkkijono", + "number": "numero", + "array": "taulukko", + "required": "pakollinen", + "default": "oletusarvo", + "default:": "oletusarvo:", + "choices:": "vaihtoehdot:", + "aliases:": "aliakset:", + "generated-value": "generoitu-arvo", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Liian vähän argumentteja, jotka eivät ole valintoja: annettu %s, vaaditaan vähintään %s", + "other": "Liian vähän argumentteja, jotka eivät ole valintoja: annettu %s, vaaditaan vähintään %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Liikaa argumentteja, jotka eivät ole valintoja: annettu %s, sallitaan enintään %s", + "other": "Liikaa argumentteja, jotka eivät ole valintoja: annettu %s, sallitaan enintään %s" + }, + "Missing argument value: %s": { + "one": "Argumentin arvo puuttuu: %s", + "other": "Argumentin arvot puuttuvat: %s" + }, + "Missing required argument: %s": { + "one": "Pakollinen argumentti puuttuu: %s", + "other": "Pakollisia argumentteja puuttuu: %s" + }, + "Unknown argument: %s": { + "one": "Tuntematon argumenttn: %s", + "other": "Tuntemattomia argumentteja: %s" + }, + "Invalid values:": "Virheelliset arvot:", + "Argument: %s, Given: %s, Choices: %s": "Argumentti: %s, Annettu: %s, Vaihtoehdot: %s", + "Argument check failed: %s": "Argumentin tarkistus epäonnistui: %s", + "Implications failed:": "Riippuvia argumentteja puuttuu:", + "Not enough arguments following: %s": "Argumentin perässä ei ole tarpeeksi argumentteja: %s", + "Invalid JSON config file: %s": "Epävalidi JSON-asetustiedosto: %s", + "Path to JSON config file": "JSON-asetustiedoston polku", + "Show help": "Näytä ohje", + "Show version number": "Näytä versionumero", + "Did you mean %s?": "Tarkoititko %s?", + "Arguments %s and %s are mutually exclusive" : "Argumentit %s ja %s eivät ole yhteensopivat", + "Positionals:": "Sijaintiparametrit:", + "command": "komento" +} diff --git a/node_modules/yargs/locales/fr.json b/node_modules/yargs/locales/fr.json new file mode 100644 index 0000000..edd743f --- /dev/null +++ b/node_modules/yargs/locales/fr.json @@ -0,0 +1,53 @@ +{ + "Commands:": "Commandes :", + "Options:": "Options :", + "Examples:": "Exemples :", + "boolean": "booléen", + "count": "compteur", + "string": "chaîne de caractères", + "number": "nombre", + "array": "tableau", + "required": "requis", + "default": "défaut", + "default:": "défaut :", + "choices:": "choix :", + "aliases:": "alias :", + "generated-value": "valeur générée", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Pas assez d'arguments (hors options) : reçu %s, besoin d'au moins %s", + "other": "Pas assez d'arguments (hors options) : reçus %s, besoin d'au moins %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Trop d'arguments (hors options) : reçu %s, maximum de %s", + "other": "Trop d'arguments (hors options) : reçus %s, maximum de %s" + }, + "Missing argument value: %s": { + "one": "Argument manquant : %s", + "other": "Arguments manquants : %s" + }, + "Missing required argument: %s": { + "one": "Argument requis manquant : %s", + "other": "Arguments requis manquants : %s" + }, + "Unknown argument: %s": { + "one": "Argument inconnu : %s", + "other": "Arguments inconnus : %s" + }, + "Unknown command: %s": { + "one": "Commande inconnue : %s", + "other": "Commandes inconnues : %s" + }, + "Invalid values:": "Valeurs invalides :", + "Argument: %s, Given: %s, Choices: %s": "Argument : %s, donné : %s, choix : %s", + "Argument check failed: %s": "Echec de la vérification de l'argument : %s", + "Implications failed:": "Arguments dépendants manquants :", + "Not enough arguments following: %s": "Pas assez d'arguments après : %s", + "Invalid JSON config file: %s": "Fichier de configuration JSON invalide : %s", + "Path to JSON config file": "Chemin du fichier de configuration JSON", + "Show help": "Affiche l'aide", + "Show version number": "Affiche le numéro de version", + "Did you mean %s?": "Vouliez-vous dire %s ?", + "Arguments %s and %s are mutually exclusive" : "Les arguments %s et %s sont mutuellement exclusifs", + "Positionals:": "Arguments positionnels :", + "command": "commande" +} diff --git a/node_modules/yargs/locales/hi.json b/node_modules/yargs/locales/hi.json new file mode 100644 index 0000000..a9de77c --- /dev/null +++ b/node_modules/yargs/locales/hi.json @@ -0,0 +1,49 @@ +{ + "Commands:": "आदेश:", + "Options:": "विकल्प:", + "Examples:": "उदाहरण:", + "boolean": "सत्यता", + "count": "संख्या", + "string": "वर्णों का तार ", + "number": "अंक", + "array": "सरणी", + "required": "आवश्यक", + "default": "डिफॉल्ट", + "default:": "डिफॉल्ट:", + "choices:": "विकल्प:", + "aliases:": "उपनाम:", + "generated-value": "उत्पन्न-मूल्य", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "पर्याप्त गैर-विकल्प तर्क प्राप्त नहीं: %s प्राप्त, कम से कम %s की आवश्यकता है", + "other": "पर्याप्त गैर-विकल्प तर्क प्राप्त नहीं: %s प्राप्त, कम से कम %s की आवश्यकता है" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "बहुत सारे गैर-विकल्प तर्क: %s प्राप्त, अधिकतम %s मान्य", + "other": "बहुत सारे गैर-विकल्प तर्क: %s प्राप्त, अधिकतम %s मान्य" + }, + "Missing argument value: %s": { + "one": "कुछ तर्को के मूल्य गुम हैं: %s", + "other": "कुछ तर्को के मूल्य गुम हैं: %s" + }, + "Missing required argument: %s": { + "one": "आवश्यक तर्क गुम हैं: %s", + "other": "आवश्यक तर्क गुम हैं: %s" + }, + "Unknown argument: %s": { + "one": "अज्ञात तर्क प्राप्त: %s", + "other": "अज्ञात तर्क प्राप्त: %s" + }, + "Invalid values:": "अमान्य मूल्य:", + "Argument: %s, Given: %s, Choices: %s": "तर्क: %s, प्राप्त: %s, विकल्प: %s", + "Argument check failed: %s": "तर्क जांच विफल: %s", + "Implications failed:": "दिए गए तर्क के लिए अतिरिक्त तर्क की अपेक्षा है:", + "Not enough arguments following: %s": "निम्नलिखित के बाद पर्याप्त तर्क नहीं प्राप्त: %s", + "Invalid JSON config file: %s": "अमान्य JSON config फाइल: %s", + "Path to JSON config file": "JSON config फाइल का पथ", + "Show help": "सहायता दिखाएँ", + "Show version number": "Version संख्या दिखाएँ", + "Did you mean %s?": "क्या आपका मतलब है %s?", + "Arguments %s and %s are mutually exclusive" : "तर्क %s और %s परस्पर अनन्य हैं", + "Positionals:": "स्थानीय:", + "command": "आदेश" +} diff --git a/node_modules/yargs/locales/hu.json b/node_modules/yargs/locales/hu.json new file mode 100644 index 0000000..21492d0 --- /dev/null +++ b/node_modules/yargs/locales/hu.json @@ -0,0 +1,46 @@ +{ + "Commands:": "Parancsok:", + "Options:": "Opciók:", + "Examples:": "Példák:", + "boolean": "boolean", + "count": "számláló", + "string": "szöveg", + "number": "szám", + "array": "tömb", + "required": "kötelező", + "default": "alapértelmezett", + "default:": "alapértelmezett:", + "choices:": "lehetőségek:", + "aliases:": "aliaszok:", + "generated-value": "generált-érték", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Nincs elég nem opcionális argumentum: %s van, legalább %s kell", + "other": "Nincs elég nem opcionális argumentum: %s van, legalább %s kell" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Túl sok nem opciánlis argumentum van: %s van, maximum %s lehet", + "other": "Túl sok nem opciánlis argumentum van: %s van, maximum %s lehet" + }, + "Missing argument value: %s": { + "one": "Hiányzó argumentum érték: %s", + "other": "Hiányzó argumentum értékek: %s" + }, + "Missing required argument: %s": { + "one": "Hiányzó kötelező argumentum: %s", + "other": "Hiányzó kötelező argumentumok: %s" + }, + "Unknown argument: %s": { + "one": "Ismeretlen argumentum: %s", + "other": "Ismeretlen argumentumok: %s" + }, + "Invalid values:": "Érvénytelen érték:", + "Argument: %s, Given: %s, Choices: %s": "Argumentum: %s, Megadott: %s, Lehetőségek: %s", + "Argument check failed: %s": "Argumentum ellenőrzés sikertelen: %s", + "Implications failed:": "Implikációk sikertelenek:", + "Not enough arguments following: %s": "Nem elég argumentum követi: %s", + "Invalid JSON config file: %s": "Érvénytelen JSON konfigurációs file: %s", + "Path to JSON config file": "JSON konfigurációs file helye", + "Show help": "Súgo megjelenítése", + "Show version number": "Verziószám megjelenítése", + "Did you mean %s?": "Erre gondoltál %s?" +} diff --git a/node_modules/yargs/locales/id.json b/node_modules/yargs/locales/id.json new file mode 100644 index 0000000..125867c --- /dev/null +++ b/node_modules/yargs/locales/id.json @@ -0,0 +1,50 @@ + +{ + "Commands:": "Perintah:", + "Options:": "Pilihan:", + "Examples:": "Contoh:", + "boolean": "boolean", + "count": "jumlah", + "number": "nomor", + "string": "string", + "array": "larik", + "required": "diperlukan", + "default": "bawaan", + "default:": "bawaan:", + "aliases:": "istilah lain:", + "choices:": "pilihan:", + "generated-value": "nilai-yang-dihasilkan", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Argumen wajib kurang: hanya %s, minimal %s", + "other": "Argumen wajib kurang: hanya %s, minimal %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Terlalu banyak argumen wajib: ada %s, maksimal %s", + "other": "Terlalu banyak argumen wajib: ada %s, maksimal %s" + }, + "Missing argument value: %s": { + "one": "Kurang argumen: %s", + "other": "Kurang argumen: %s" + }, + "Missing required argument: %s": { + "one": "Kurang argumen wajib: %s", + "other": "Kurang argumen wajib: %s" + }, + "Unknown argument: %s": { + "one": "Argumen tak diketahui: %s", + "other": "Argumen tak diketahui: %s" + }, + "Invalid values:": "Nilai-nilai tidak valid:", + "Argument: %s, Given: %s, Choices: %s": "Argumen: %s, Diberikan: %s, Pilihan: %s", + "Argument check failed: %s": "Pemeriksaan argument gagal: %s", + "Implications failed:": "Implikasi gagal:", + "Not enough arguments following: %s": "Kurang argumen untuk: %s", + "Invalid JSON config file: %s": "Berkas konfigurasi JSON tidak valid: %s", + "Path to JSON config file": "Alamat berkas konfigurasi JSON", + "Show help": "Lihat bantuan", + "Show version number": "Lihat nomor versi", + "Did you mean %s?": "Maksud Anda: %s?", + "Arguments %s and %s are mutually exclusive" : "Argumen %s dan %s saling eksklusif", + "Positionals:": "Posisional-posisional:", + "command": "perintah" +} diff --git a/node_modules/yargs/locales/it.json b/node_modules/yargs/locales/it.json new file mode 100644 index 0000000..fde5756 --- /dev/null +++ b/node_modules/yargs/locales/it.json @@ -0,0 +1,46 @@ +{ + "Commands:": "Comandi:", + "Options:": "Opzioni:", + "Examples:": "Esempi:", + "boolean": "booleano", + "count": "contatore", + "string": "stringa", + "number": "numero", + "array": "vettore", + "required": "richiesto", + "default": "predefinito", + "default:": "predefinito:", + "choices:": "scelte:", + "aliases:": "alias:", + "generated-value": "valore generato", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Numero insufficiente di argomenti non opzione: inseriti %s, richiesti almeno %s", + "other": "Numero insufficiente di argomenti non opzione: inseriti %s, richiesti almeno %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Troppi argomenti non opzione: inseriti %s, massimo possibile %s", + "other": "Troppi argomenti non opzione: inseriti %s, massimo possibile %s" + }, + "Missing argument value: %s": { + "one": "Argomento mancante: %s", + "other": "Argomenti mancanti: %s" + }, + "Missing required argument: %s": { + "one": "Argomento richiesto mancante: %s", + "other": "Argomenti richiesti mancanti: %s" + }, + "Unknown argument: %s": { + "one": "Argomento sconosciuto: %s", + "other": "Argomenti sconosciuti: %s" + }, + "Invalid values:": "Valori non validi:", + "Argument: %s, Given: %s, Choices: %s": "Argomento: %s, Richiesto: %s, Scelte: %s", + "Argument check failed: %s": "Controllo dell'argomento fallito: %s", + "Implications failed:": "Argomenti dipendenti mancanti:", + "Not enough arguments following: %s": "Argomenti insufficienti dopo: %s", + "Invalid JSON config file: %s": "File di configurazione JSON non valido: %s", + "Path to JSON config file": "Percorso del file di configurazione JSON", + "Show help": "Mostra la schermata di aiuto", + "Show version number": "Mostra il numero di versione", + "Did you mean %s?": "Intendi forse %s?" +} diff --git a/node_modules/yargs/locales/ja.json b/node_modules/yargs/locales/ja.json new file mode 100644 index 0000000..3954ae6 --- /dev/null +++ b/node_modules/yargs/locales/ja.json @@ -0,0 +1,51 @@ +{ + "Commands:": "コマンド:", + "Options:": "オプション:", + "Examples:": "例:", + "boolean": "真偽", + "count": "カウント", + "string": "文字列", + "number": "数値", + "array": "配列", + "required": "必須", + "default": "デフォルト", + "default:": "デフォルト:", + "choices:": "選択してください:", + "aliases:": "エイリアス:", + "generated-value": "生成された値", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "オプションではない引数が %s 個では不足しています。少なくとも %s 個の引数が必要です:", + "other": "オプションではない引数が %s 個では不足しています。少なくとも %s 個の引数が必要です:" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "オプションではない引数が %s 個では多すぎます。最大で %s 個までです:", + "other": "オプションではない引数が %s 個では多すぎます。最大で %s 個までです:" + }, + "Missing argument value: %s": { + "one": "引数の値が見つかりません: %s", + "other": "引数の値が見つかりません: %s" + }, + "Missing required argument: %s": { + "one": "必須の引数が見つかりません: %s", + "other": "必須の引数が見つかりません: %s" + }, + "Unknown argument: %s": { + "one": "未知の引数です: %s", + "other": "未知の引数です: %s" + }, + "Invalid values:": "不正な値です:", + "Argument: %s, Given: %s, Choices: %s": "引数は %s です。与えられた値: %s, 選択してください: %s", + "Argument check failed: %s": "引数のチェックに失敗しました: %s", + "Implications failed:": "オプションの組み合わせで不正が生じました:", + "Not enough arguments following: %s": "次の引数が不足しています。: %s", + "Invalid JSON config file: %s": "JSONの設定ファイルが不正です: %s", + "Path to JSON config file": "JSONの設定ファイルまでのpath", + "Show help": "ヘルプを表示", + "Show version number": "バージョンを表示", + "Did you mean %s?": "もしかして %s?", + "Arguments %s and %s are mutually exclusive" : "引数 %s と %s は同時に指定できません", + "Positionals:": "位置:", + "command": "コマンド", + "deprecated": "非推奨", + "deprecated: %s": "非推奨: %s" +} diff --git a/node_modules/yargs/locales/ko.json b/node_modules/yargs/locales/ko.json new file mode 100644 index 0000000..e3187ea --- /dev/null +++ b/node_modules/yargs/locales/ko.json @@ -0,0 +1,49 @@ +{ + "Commands:": "명령:", + "Options:": "옵션:", + "Examples:": "예시:", + "boolean": "여부", + "count": "개수", + "string": "문자열", + "number": "숫자", + "array": "배열", + "required": "필수", + "default": "기본", + "default:": "기본:", + "choices:": "선택:", + "aliases:": "별칭:", + "generated-value": "생성된 값", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "옵션이 아닌 인자가 충분치 않습니다: %s개를 받았지만, 적어도 %s개는 필요합니다", + "other": "옵션이 아닌 인자가 충분치 않습니다: %s개를 받았지만, 적어도 %s개는 필요합니다" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "옵션이 아닌 인자가 너무 많습니다: %s개를 받았지만, %s개 이하여야 합니다", + "other": "옵션이 아닌 인자가 너무 많습니다: %s개를 받았지만, %s개 이하여야 합니다" + }, + "Missing argument value: %s": { + "one": "인자값을 받지 못했습니다: %s", + "other": "인자값들을 받지 못했습니다: %s" + }, + "Missing required argument: %s": { + "one": "필수 인자를 받지 못했습니다: %s", + "other": "필수 인자들을 받지 못했습니다: %s" + }, + "Unknown argument: %s": { + "one": "알 수 없는 인자입니다: %s", + "other": "알 수 없는 인자들입니다: %s" + }, + "Invalid values:": "잘못된 값입니다:", + "Argument: %s, Given: %s, Choices: %s": "인자: %s, 입력받은 값: %s, 선택지: %s", + "Argument check failed: %s": "유효하지 않은 인자입니다: %s", + "Implications failed:": "옵션의 조합이 잘못되었습니다:", + "Not enough arguments following: %s": "인자가 충분하게 주어지지 않았습니다: %s", + "Invalid JSON config file: %s": "유효하지 않은 JSON 설정파일입니다: %s", + "Path to JSON config file": "JSON 설정파일 경로", + "Show help": "도움말을 보여줍니다", + "Show version number": "버전 넘버를 보여줍니다", + "Did you mean %s?": "찾고계신게 %s입니까?", + "Arguments %s and %s are mutually exclusive" : "%s와 %s 인자는 같이 사용될 수 없습니다", + "Positionals:": "위치:", + "command": "명령" +} diff --git a/node_modules/yargs/locales/nb.json b/node_modules/yargs/locales/nb.json new file mode 100644 index 0000000..6f410ed --- /dev/null +++ b/node_modules/yargs/locales/nb.json @@ -0,0 +1,44 @@ +{ + "Commands:": "Kommandoer:", + "Options:": "Alternativer:", + "Examples:": "Eksempler:", + "boolean": "boolsk", + "count": "antall", + "string": "streng", + "number": "nummer", + "array": "matrise", + "required": "obligatorisk", + "default": "standard", + "default:": "standard:", + "choices:": "valg:", + "generated-value": "generert-verdi", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Ikke nok ikke-alternativ argumenter: fikk %s, trenger minst %s", + "other": "Ikke nok ikke-alternativ argumenter: fikk %s, trenger minst %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "For mange ikke-alternativ argumenter: fikk %s, maksimum %s", + "other": "For mange ikke-alternativ argumenter: fikk %s, maksimum %s" + }, + "Missing argument value: %s": { + "one": "Mangler argument verdi: %s", + "other": "Mangler argument verdier: %s" + }, + "Missing required argument: %s": { + "one": "Mangler obligatorisk argument: %s", + "other": "Mangler obligatoriske argumenter: %s" + }, + "Unknown argument: %s": { + "one": "Ukjent argument: %s", + "other": "Ukjente argumenter: %s" + }, + "Invalid values:": "Ugyldige verdier:", + "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Gitt: %s, Valg: %s", + "Argument check failed: %s": "Argumentsjekk mislyktes: %s", + "Implications failed:": "Konsekvensene mislyktes:", + "Not enough arguments following: %s": "Ikke nok følgende argumenter: %s", + "Invalid JSON config file: %s": "Ugyldig JSON konfigurasjonsfil: %s", + "Path to JSON config file": "Bane til JSON konfigurasjonsfil", + "Show help": "Vis hjelp", + "Show version number": "Vis versjonsnummer" +} diff --git a/node_modules/yargs/locales/nl.json b/node_modules/yargs/locales/nl.json new file mode 100644 index 0000000..9ff95c5 --- /dev/null +++ b/node_modules/yargs/locales/nl.json @@ -0,0 +1,49 @@ +{ + "Commands:": "Commando's:", + "Options:": "Opties:", + "Examples:": "Voorbeelden:", + "boolean": "booleaans", + "count": "aantal", + "string": "string", + "number": "getal", + "array": "lijst", + "required": "verplicht", + "default": "standaard", + "default:": "standaard:", + "choices:": "keuzes:", + "aliases:": "aliassen:", + "generated-value": "gegenereerde waarde", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Niet genoeg niet-optie-argumenten: %s gekregen, minstens %s nodig", + "other": "Niet genoeg niet-optie-argumenten: %s gekregen, minstens %s nodig" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Te veel niet-optie-argumenten: %s gekregen, maximum is %s", + "other": "Te veel niet-optie-argumenten: %s gekregen, maximum is %s" + }, + "Missing argument value: %s": { + "one": "Missende argumentwaarde: %s", + "other": "Missende argumentwaarden: %s" + }, + "Missing required argument: %s": { + "one": "Missend verplicht argument: %s", + "other": "Missende verplichte argumenten: %s" + }, + "Unknown argument: %s": { + "one": "Onbekend argument: %s", + "other": "Onbekende argumenten: %s" + }, + "Invalid values:": "Ongeldige waarden:", + "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Gegeven: %s, Keuzes: %s", + "Argument check failed: %s": "Argumentcontrole mislukt: %s", + "Implications failed:": "Ontbrekende afhankelijke argumenten:", + "Not enough arguments following: %s": "Niet genoeg argumenten na: %s", + "Invalid JSON config file: %s": "Ongeldig JSON-config-bestand: %s", + "Path to JSON config file": "Pad naar JSON-config-bestand", + "Show help": "Toon help", + "Show version number": "Toon versienummer", + "Did you mean %s?": "Bedoelde u misschien %s?", + "Arguments %s and %s are mutually exclusive": "Argumenten %s en %s kunnen niet tegelijk gebruikt worden", + "Positionals:": "Positie-afhankelijke argumenten", + "command": "commando" +} diff --git a/node_modules/yargs/locales/nn.json b/node_modules/yargs/locales/nn.json new file mode 100644 index 0000000..24479ac --- /dev/null +++ b/node_modules/yargs/locales/nn.json @@ -0,0 +1,44 @@ +{ + "Commands:": "Kommandoar:", + "Options:": "Alternativ:", + "Examples:": "Døme:", + "boolean": "boolsk", + "count": "mengd", + "string": "streng", + "number": "nummer", + "array": "matrise", + "required": "obligatorisk", + "default": "standard", + "default:": "standard:", + "choices:": "val:", + "generated-value": "generert-verdi", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Ikkje nok ikkje-alternativ argument: fekk %s, treng minst %s", + "other": "Ikkje nok ikkje-alternativ argument: fekk %s, treng minst %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "For mange ikkje-alternativ argument: fekk %s, maksimum %s", + "other": "For mange ikkje-alternativ argument: fekk %s, maksimum %s" + }, + "Missing argument value: %s": { + "one": "Manglar argumentverdi: %s", + "other": "Manglar argumentverdiar: %s" + }, + "Missing required argument: %s": { + "one": "Manglar obligatorisk argument: %s", + "other": "Manglar obligatoriske argument: %s" + }, + "Unknown argument: %s": { + "one": "Ukjent argument: %s", + "other": "Ukjende argument: %s" + }, + "Invalid values:": "Ugyldige verdiar:", + "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Gjeve: %s, Val: %s", + "Argument check failed: %s": "Argumentsjekk mislukkast: %s", + "Implications failed:": "Konsekvensane mislukkast:", + "Not enough arguments following: %s": "Ikkje nok fylgjande argument: %s", + "Invalid JSON config file: %s": "Ugyldig JSON konfigurasjonsfil: %s", + "Path to JSON config file": "Bane til JSON konfigurasjonsfil", + "Show help": "Vis hjelp", + "Show version number": "Vis versjonsnummer" +} diff --git a/node_modules/yargs/locales/pirate.json b/node_modules/yargs/locales/pirate.json new file mode 100644 index 0000000..dcb5cb7 --- /dev/null +++ b/node_modules/yargs/locales/pirate.json @@ -0,0 +1,13 @@ +{ + "Commands:": "Choose yer command:", + "Options:": "Options for me hearties!", + "Examples:": "Ex. marks the spot:", + "required": "requi-yar-ed", + "Missing required argument: %s": { + "one": "Ye be havin' to set the followin' argument land lubber: %s", + "other": "Ye be havin' to set the followin' arguments land lubber: %s" + }, + "Show help": "Parlay this here code of conduct", + "Show version number": "'Tis the version ye be askin' fer", + "Arguments %s and %s are mutually exclusive" : "Yon scurvy dogs %s and %s be as bad as rum and a prudish wench" +} diff --git a/node_modules/yargs/locales/pl.json b/node_modules/yargs/locales/pl.json new file mode 100644 index 0000000..a41d4bd --- /dev/null +++ b/node_modules/yargs/locales/pl.json @@ -0,0 +1,49 @@ +{ + "Commands:": "Polecenia:", + "Options:": "Opcje:", + "Examples:": "Przykłady:", + "boolean": "boolean", + "count": "ilość", + "string": "ciąg znaków", + "number": "liczba", + "array": "tablica", + "required": "wymagany", + "default": "domyślny", + "default:": "domyślny:", + "choices:": "dostępne:", + "aliases:": "aliasy:", + "generated-value": "wygenerowana-wartość", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Niewystarczająca ilość argumentów: otrzymano %s, wymagane co najmniej %s", + "other": "Niewystarczająca ilość argumentów: otrzymano %s, wymagane co najmniej %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Zbyt duża ilość argumentów: otrzymano %s, wymagane co najwyżej %s", + "other": "Zbyt duża ilość argumentów: otrzymano %s, wymagane co najwyżej %s" + }, + "Missing argument value: %s": { + "one": "Brak wartości dla argumentu: %s", + "other": "Brak wartości dla argumentów: %s" + }, + "Missing required argument: %s": { + "one": "Brak wymaganego argumentu: %s", + "other": "Brak wymaganych argumentów: %s" + }, + "Unknown argument: %s": { + "one": "Nieznany argument: %s", + "other": "Nieznane argumenty: %s" + }, + "Invalid values:": "Nieprawidłowe wartości:", + "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Otrzymano: %s, Dostępne: %s", + "Argument check failed: %s": "Weryfikacja argumentów nie powiodła się: %s", + "Implications failed:": "Założenia nie zostały spełnione:", + "Not enough arguments following: %s": "Niewystarczająca ilość argumentów następujących po: %s", + "Invalid JSON config file: %s": "Nieprawidłowy plik konfiguracyjny JSON: %s", + "Path to JSON config file": "Ścieżka do pliku konfiguracyjnego JSON", + "Show help": "Pokaż pomoc", + "Show version number": "Pokaż numer wersji", + "Did you mean %s?": "Czy chodziło Ci o %s?", + "Arguments %s and %s are mutually exclusive": "Argumenty %s i %s wzajemnie się wykluczają", + "Positionals:": "Pozycyjne:", + "command": "polecenie" +} diff --git a/node_modules/yargs/locales/pt.json b/node_modules/yargs/locales/pt.json new file mode 100644 index 0000000..0c8ac99 --- /dev/null +++ b/node_modules/yargs/locales/pt.json @@ -0,0 +1,45 @@ +{ + "Commands:": "Comandos:", + "Options:": "Opções:", + "Examples:": "Exemplos:", + "boolean": "boolean", + "count": "contagem", + "string": "cadeia de caracteres", + "number": "número", + "array": "arranjo", + "required": "requerido", + "default": "padrão", + "default:": "padrão:", + "choices:": "escolhas:", + "generated-value": "valor-gerado", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Argumentos insuficientes não opcionais: Argumento %s, necessário pelo menos %s", + "other": "Argumentos insuficientes não opcionais: Argumento %s, necessário pelo menos %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Excesso de argumentos não opcionais: recebido %s, máximo de %s", + "other": "Excesso de argumentos não opcionais: recebido %s, máximo de %s" + }, + "Missing argument value: %s": { + "one": "Falta valor de argumento: %s", + "other": "Falta valores de argumento: %s" + }, + "Missing required argument: %s": { + "one": "Falta argumento obrigatório: %s", + "other": "Faltando argumentos obrigatórios: %s" + }, + "Unknown argument: %s": { + "one": "Argumento desconhecido: %s", + "other": "Argumentos desconhecidos: %s" + }, + "Invalid values:": "Valores inválidos:", + "Argument: %s, Given: %s, Choices: %s": "Argumento: %s, Dado: %s, Escolhas: %s", + "Argument check failed: %s": "Verificação de argumento falhou: %s", + "Implications failed:": "Implicações falharam:", + "Not enough arguments following: %s": "Insuficientes argumentos a seguir: %s", + "Invalid JSON config file: %s": "Arquivo de configuração em JSON esta inválido: %s", + "Path to JSON config file": "Caminho para o arquivo de configuração em JSON", + "Show help": "Mostra ajuda", + "Show version number": "Mostra número de versão", + "Arguments %s and %s are mutually exclusive" : "Argumentos %s e %s são mutualmente exclusivos" +} diff --git a/node_modules/yargs/locales/pt_BR.json b/node_modules/yargs/locales/pt_BR.json new file mode 100644 index 0000000..eae1ec6 --- /dev/null +++ b/node_modules/yargs/locales/pt_BR.json @@ -0,0 +1,48 @@ +{ + "Commands:": "Comandos:", + "Options:": "Opções:", + "Examples:": "Exemplos:", + "boolean": "booleano", + "count": "contagem", + "string": "string", + "number": "número", + "array": "array", + "required": "obrigatório", + "default:": "padrão:", + "choices:": "opções:", + "aliases:": "sinônimos:", + "generated-value": "valor-gerado", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Argumentos insuficientes: Argumento %s, necessário pelo menos %s", + "other": "Argumentos insuficientes: Argumento %s, necessário pelo menos %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Excesso de argumentos: recebido %s, máximo de %s", + "other": "Excesso de argumentos: recebido %s, máximo de %s" + }, + "Missing argument value: %s": { + "one": "Falta valor de argumento: %s", + "other": "Falta valores de argumento: %s" + }, + "Missing required argument: %s": { + "one": "Falta argumento obrigatório: %s", + "other": "Faltando argumentos obrigatórios: %s" + }, + "Unknown argument: %s": { + "one": "Argumento desconhecido: %s", + "other": "Argumentos desconhecidos: %s" + }, + "Invalid values:": "Valores inválidos:", + "Argument: %s, Given: %s, Choices: %s": "Argumento: %s, Dado: %s, Opções: %s", + "Argument check failed: %s": "Verificação de argumento falhou: %s", + "Implications failed:": "Implicações falharam:", + "Not enough arguments following: %s": "Argumentos insuficientes a seguir: %s", + "Invalid JSON config file: %s": "Arquivo JSON de configuração inválido: %s", + "Path to JSON config file": "Caminho para o arquivo JSON de configuração", + "Show help": "Exibe ajuda", + "Show version number": "Exibe a versão", + "Did you mean %s?": "Você quis dizer %s?", + "Arguments %s and %s are mutually exclusive" : "Argumentos %s e %s são mutualmente exclusivos", + "Positionals:": "Posicionais:", + "command": "comando" +} diff --git a/node_modules/yargs/locales/ru.json b/node_modules/yargs/locales/ru.json new file mode 100644 index 0000000..5f7f768 --- /dev/null +++ b/node_modules/yargs/locales/ru.json @@ -0,0 +1,46 @@ +{ + "Commands:": "Команды:", + "Options:": "Опции:", + "Examples:": "Примеры:", + "boolean": "булевый тип", + "count": "подсчет", + "string": "строковой тип", + "number": "число", + "array": "массив", + "required": "необходимо", + "default": "по умолчанию", + "default:": "по умолчанию:", + "choices:": "возможности:", + "aliases:": "алиасы:", + "generated-value": "генерированное значение", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Недостаточно неопционных аргументов: есть %s, нужно как минимум %s", + "other": "Недостаточно неопционных аргументов: есть %s, нужно как минимум %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Слишком много неопционных аргументов: есть %s, максимум допустимо %s", + "other": "Слишком много неопционных аргументов: есть %s, максимум допустимо %s" + }, + "Missing argument value: %s": { + "one": "Не хватает значения аргумента: %s", + "other": "Не хватает значений аргументов: %s" + }, + "Missing required argument: %s": { + "one": "Не хватает необходимого аргумента: %s", + "other": "Не хватает необходимых аргументов: %s" + }, + "Unknown argument: %s": { + "one": "Неизвестный аргумент: %s", + "other": "Неизвестные аргументы: %s" + }, + "Invalid values:": "Недействительные значения:", + "Argument: %s, Given: %s, Choices: %s": "Аргумент: %s, Данное значение: %s, Возможности: %s", + "Argument check failed: %s": "Проверка аргументов не удалась: %s", + "Implications failed:": "Данный аргумент требует следующий дополнительный аргумент:", + "Not enough arguments following: %s": "Недостаточно следующих аргументов: %s", + "Invalid JSON config file: %s": "Недействительный файл конфигурации JSON: %s", + "Path to JSON config file": "Путь к файлу конфигурации JSON", + "Show help": "Показать помощь", + "Show version number": "Показать номер версии", + "Did you mean %s?": "Вы имели в виду %s?" +} diff --git a/node_modules/yargs/locales/th.json b/node_modules/yargs/locales/th.json new file mode 100644 index 0000000..33b048e --- /dev/null +++ b/node_modules/yargs/locales/th.json @@ -0,0 +1,46 @@ +{ + "Commands:": "คอมมาน", + "Options:": "ออฟชั่น", + "Examples:": "ตัวอย่าง", + "boolean": "บูลีน", + "count": "นับ", + "string": "สตริง", + "number": "ตัวเลข", + "array": "อาเรย์", + "required": "จำเป็น", + "default": "ค่าเริ่มต้", + "default:": "ค่าเริ่มต้น", + "choices:": "ตัวเลือก", + "aliases:": "เอเลียส", + "generated-value": "ค่าที่ถูกสร้างขึ้น", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "ใส่อาร์กิวเมนต์ไม่ครบตามจำนวนที่กำหนด: ใส่ค่ามาจำนวน %s ค่า, แต่ต้องการอย่างน้อย %s ค่า", + "other": "ใส่อาร์กิวเมนต์ไม่ครบตามจำนวนที่กำหนด: ใส่ค่ามาจำนวน %s ค่า, แต่ต้องการอย่างน้อย %s ค่า" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "ใส่อาร์กิวเมนต์เกินจำนวนที่กำหนด: ใส่ค่ามาจำนวน %s ค่า, แต่ต้องการมากที่สุด %s ค่า", + "other": "ใส่อาร์กิวเมนต์เกินจำนวนที่กำหนด: ใส่ค่ามาจำนวน %s ค่า, แต่ต้องการมากที่สุด %s ค่า" + }, + "Missing argument value: %s": { + "one": "ค่าอาร์กิวเมนต์ที่ขาดไป: %s", + "other": "ค่าอาร์กิวเมนต์ที่ขาดไป: %s" + }, + "Missing required argument: %s": { + "one": "อาร์กิวเมนต์จำเป็นที่ขาดไป: %s", + "other": "อาร์กิวเมนต์จำเป็นที่ขาดไป: %s" + }, + "Unknown argument: %s": { + "one": "อาร์กิวเมนต์ที่ไม่รู้จัก: %s", + "other": "อาร์กิวเมนต์ที่ไม่รู้จัก: %s" + }, + "Invalid values:": "ค่าไม่ถูกต้อง:", + "Argument: %s, Given: %s, Choices: %s": "อาร์กิวเมนต์: %s, ได้รับ: %s, ตัวเลือก: %s", + "Argument check failed: %s": "ตรวจสอบพบอาร์กิวเมนต์ที่ไม่ถูกต้อง: %s", + "Implications failed:": "Implications ไม่สำเร็จ:", + "Not enough arguments following: %s": "ใส่อาร์กิวเมนต์ไม่ครบ: %s", + "Invalid JSON config file: %s": "ไฟล์คอนฟิค JSON ไม่ถูกต้อง: %s", + "Path to JSON config file": "พาทไฟล์คอนฟิค JSON", + "Show help": "ขอความช่วยเหลือ", + "Show version number": "แสดงตัวเลขเวอร์ชั่น", + "Did you mean %s?": "คุณหมายถึง %s?" +} diff --git a/node_modules/yargs/locales/tr.json b/node_modules/yargs/locales/tr.json new file mode 100644 index 0000000..0d0d2cc --- /dev/null +++ b/node_modules/yargs/locales/tr.json @@ -0,0 +1,48 @@ +{ + "Commands:": "Komutlar:", + "Options:": "Seçenekler:", + "Examples:": "Örnekler:", + "boolean": "boolean", + "count": "sayı", + "string": "string", + "number": "numara", + "array": "array", + "required": "zorunlu", + "default": "varsayılan", + "default:": "varsayılan:", + "choices:": "seçimler:", + "aliases:": "takma adlar:", + "generated-value": "oluşturulan-değer", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Seçenek dışı argümanlar yetersiz: %s bulundu, %s gerekli", + "other": "Seçenek dışı argümanlar yetersiz: %s bulundu, %s gerekli" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Seçenek dışı argümanlar gereğinden fazla: %s bulundu, azami %s", + "other": "Seçenek dışı argümanlar gereğinden fazla: %s bulundu, azami %s" + }, + "Missing argument value: %s": { + "one": "Eksik argüman değeri: %s", + "other": "Eksik argüman değerleri: %s" + }, + "Missing required argument: %s": { + "one": "Eksik zorunlu argüman: %s", + "other": "Eksik zorunlu argümanlar: %s" + }, + "Unknown argument: %s": { + "one": "Bilinmeyen argüman: %s", + "other": "Bilinmeyen argümanlar: %s" + }, + "Invalid values:": "Geçersiz değerler:", + "Argument: %s, Given: %s, Choices: %s": "Argüman: %s, Verilen: %s, Seçimler: %s", + "Argument check failed: %s": "Argüman kontrolü başarısız oldu: %s", + "Implications failed:": "Sonuçlar başarısız oldu:", + "Not enough arguments following: %s": "%s için yeterli argüman bulunamadı", + "Invalid JSON config file: %s": "Geçersiz JSON yapılandırma dosyası: %s", + "Path to JSON config file": "JSON yapılandırma dosya konumu", + "Show help": "Yardım detaylarını göster", + "Show version number": "Versiyon detaylarını göster", + "Did you mean %s?": "Bunu mu demek istediniz: %s?", + "Positionals:": "Sıralılar:", + "command": "komut" +} diff --git a/node_modules/yargs/locales/zh_CN.json b/node_modules/yargs/locales/zh_CN.json new file mode 100644 index 0000000..257d26b --- /dev/null +++ b/node_modules/yargs/locales/zh_CN.json @@ -0,0 +1,48 @@ +{ + "Commands:": "命令:", + "Options:": "选项:", + "Examples:": "示例:", + "boolean": "布尔", + "count": "计数", + "string": "字符串", + "number": "数字", + "array": "数组", + "required": "必需", + "default": "默认值", + "default:": "默认值:", + "choices:": "可选值:", + "generated-value": "生成的值", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "缺少 non-option 参数:传入了 %s 个, 至少需要 %s 个", + "other": "缺少 non-option 参数:传入了 %s 个, 至少需要 %s 个" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "non-option 参数过多:传入了 %s 个, 最大允许 %s 个", + "other": "non-option 参数过多:传入了 %s 个, 最大允许 %s 个" + }, + "Missing argument value: %s": { + "one": "没有给此选项指定值:%s", + "other": "没有给这些选项指定值:%s" + }, + "Missing required argument: %s": { + "one": "缺少必须的选项:%s", + "other": "缺少这些必须的选项:%s" + }, + "Unknown argument: %s": { + "one": "无法识别的选项:%s", + "other": "无法识别这些选项:%s" + }, + "Invalid values:": "无效的选项值:", + "Argument: %s, Given: %s, Choices: %s": "选项名称: %s, 传入的值: %s, 可选的值:%s", + "Argument check failed: %s": "选项值验证失败:%s", + "Implications failed:": "缺少依赖的选项:", + "Not enough arguments following: %s": "没有提供足够的值给此选项:%s", + "Invalid JSON config file: %s": "无效的 JSON 配置文件:%s", + "Path to JSON config file": "JSON 配置文件的路径", + "Show help": "显示帮助信息", + "Show version number": "显示版本号", + "Did you mean %s?": "是指 %s?", + "Arguments %s and %s are mutually exclusive" : "选项 %s 和 %s 是互斥的", + "Positionals:": "位置:", + "command": "命令" +} diff --git a/node_modules/yargs/locales/zh_TW.json b/node_modules/yargs/locales/zh_TW.json new file mode 100644 index 0000000..e3c7bcf --- /dev/null +++ b/node_modules/yargs/locales/zh_TW.json @@ -0,0 +1,47 @@ +{ + "Commands:": "命令:", + "Options:": "選項:", + "Examples:": "例:", + "boolean": "布林", + "count": "次數", + "string": "字串", + "number": "數字", + "array": "陣列", + "required": "必須", + "default": "預設值", + "default:": "預設值:", + "choices:": "可選值:", + "aliases:": "別名:", + "generated-value": "生成的值", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "non-option 引數不足:只傳入了 %s 個, 至少要 %s 個", + "other": "non-option 引數不足:只傳入了 %s 個, 至少要 %s 個" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "non-option 引數過多:傳入了 %s 個, 但最多 %s 個", + "other": "non-option 引數過多:傳入了 %s 個, 但最多 %s 個" + }, + "Missing argument value: %s": { + "one": "此引數無指定值:%s", + "other": "這些引數無指定值:%s" + }, + "Missing required argument: %s": { + "one": "缺少必須的引數:%s", + "other": "缺少這些必須的引數:%s" + }, + "Unknown argument: %s": { + "one": "未知的引數:%s", + "other": "未知的這些引數:%s" + }, + "Invalid values:": "無效的選項值:", + "Argument: %s, Given: %s, Choices: %s": "引數名稱: %s, 傳入的值: %s, 可選的值:%s", + "Argument check failed: %s": "引數驗證失敗:%s", + "Implications failed:": "缺少依賴的選項:", + "Not enough arguments following: %s": "沒有提供足夠的值給此引數:%s", + "Invalid JSON config file: %s": "無效的 JSON 設置文件:%s", + "Path to JSON config file": "JSON 設置文件的路徑", + "Show help": "顯示說明", + "Show version number": "顯示版本", + "Did you mean %s?": "是指 %s?", + "Arguments %s and %s are mutually exclusive" : "引數 %s 和 %s 是互斥的" +} diff --git a/node_modules/yargs/package.json b/node_modules/yargs/package.json new file mode 100644 index 0000000..dc3018a --- /dev/null +++ b/node_modules/yargs/package.json @@ -0,0 +1,92 @@ +{ + "name": "yargs", + "version": "15.4.1", + "description": "yargs the modern, pirate-themed, successor to optimist.", + "main": "./index.js", + "contributors": [ + { + "name": "Yargs Contributors", + "url": "https://github.com/yargs/yargs/graphs/contributors" + } + ], + "files": [ + "index.js", + "yargs.js", + "build", + "locales", + "LICENSE" + ], + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "devDependencies": { + "@types/chai": "^4.2.11", + "@types/decamelize": "^1.2.0", + "@types/mocha": "^7.0.2", + "@types/node": "^10.0.3", + "@typescript-eslint/eslint-plugin": "^3.0.0", + "@typescript-eslint/parser": "^3.0.0", + "c8": "^7.0.0", + "chai": "^4.2.0", + "chalk": "^4.0.0", + "coveralls": "^3.0.9", + "cpr": "^3.0.1", + "cross-spawn": "^7.0.0", + "es6-promise": "^4.2.5", + "eslint": "^6.8.0", + "eslint-plugin-import": "^2.20.1", + "eslint-plugin-node": "^11.0.0", + "gts": "^2.0.0-alpha.4", + "hashish": "0.0.4", + "mocha": "^7.0.0", + "rimraf": "^3.0.2", + "standardx": "^5.0.0", + "typescript": "^3.7.0", + "which": "^2.0.0", + "yargs-test-extends": "^1.0.1" + }, + "scripts": { + "fix": "standardx --fix && standardx --fix **/*.ts", + "posttest": "npm run check", + "test": "c8 mocha --require ./test/before.js --timeout=12000 --check-leaks", + "coverage": "c8 report --check-coverage", + "check": "standardx && standardx **/*.ts", + "compile": "rimraf build && tsc", + "prepare": "npm run compile", + "pretest": "npm run compile -- -p tsconfig.test.json" + }, + "repository": { + "type": "git", + "url": "https://github.com/yargs/yargs.git" + }, + "homepage": "https://yargs.js.org/", + "standardx": { + "ignore": [ + "build", + "**/example/**" + ] + }, + "keywords": [ + "argument", + "args", + "option", + "parser", + "parsing", + "cli", + "command" + ], + "license": "MIT", + "engines": { + "node": ">=8" + } +} diff --git a/node_modules/yargs/yargs.js b/node_modules/yargs/yargs.js new file mode 100644 index 0000000..93e8059 --- /dev/null +++ b/node_modules/yargs/yargs.js @@ -0,0 +1,14 @@ +'use strict' + +// an async function fails early in Node.js versions prior to 8. +async function requiresNode8OrGreater () {} +requiresNode8OrGreater() + +const { Yargs, rebase } = require('./build/lib/yargs') +const Parser = require('yargs-parser') + +exports = module.exports = Yargs +exports.rebase = rebase + +// allow consumers to directly use the version of yargs-parser used by yargs +exports.Parser = Parser diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..8ba1415 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,808 @@ +{ + "name": "public", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "public", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "qrcode": "^1.5.4" + }, + "devDependencies": { + "esbuild": "^0.25.9" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..f5f8fad --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "public", + "version": "1.0.0", + "description": "
", + "main": "sw.js", + "directories": { + "doc": "doc" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "esbuild": "^0.25.9" + }, + "dependencies": { + "qrcode": "^1.5.4" + } +} diff --git a/src/app.jsx b/src/app.jsx new file mode 100644 index 0000000..3ee2be5 --- /dev/null +++ b/src/app.jsx @@ -0,0 +1,3732 @@ + + // Slider Component + const UniqueFeatureSlider = () => { + const [currentSlide, setCurrentSlide] = React.useState(0); + + const slides = [ + { + icon: "fas fa-shield-halved", + color: "orange", + title: "18-Layer Military Security", + description: "Revolutionary defense system with ECDH P-384 + AES-GCM 256 + ECDSA + Complete ASN.1 Validation. Enhanced Security Edition provides military-grade protection exceeding government standards with complete key structure verification." + }, + { + icon: "fas fa-bolt", + color: "yellow", + title: "Lightning Network Payments", + description: "First messenger with Lightning Network integration. Pay-per-session with satoshis via WebLN. Sustainable economic model without ads or data harvesting." + }, + { + icon: "fas fa-network-wired", + color: "purple", + title: "Pure P2P WebRTC Architecture", + description: "Direct peer-to-peer connections without any servers. Impossible to censor, block, or monitor. Complete decentralization with zero infrastructure." + }, + { + icon: "fas fa-sync-alt", + color: "green", + title: "Perfect Forward Secrecy", + description: "Automatic key rotation every 5 minutes or 100 messages. Non-extractable keys with hardware protection ensure past messages remain secure." + }, + { + icon: "fas fa-user-secret", + color: "cyan", + title: "Advanced Traffic Obfuscation", + description: "Fake traffic generation, packet padding, and pattern masking make communication indistinguishable from random noise. Defeats traffic analysis." + }, + { + icon: "fas fa-eye-slash", + color: "blue", + title: "Zero Data Collection", + description: "No registration, no servers, no logs. Messages exist only in browser memory. Complete anonymity with instant anonymous channels." + }, + { + icon: "fas fa-code", + color: "emerald", + title: "100% Open Source Security", + description: "All code is open for audit under MIT license. Uses only standard WebCrypto APIs. Cryptography runs directly in browser without server dependencies." + } + ]; + + const nextSlide = () => setCurrentSlide((prev) => (prev + 1) % slides.length); + const prevSlide = () => setCurrentSlide((prev) => (prev - 1 + slides.length) % slides.length); + const goToSlide = (index) => setCurrentSlide(index); + + React.useEffect(() => { + const timer = setInterval(() => { + nextSlide(); + }, 15000); + return () => clearInterval(timer); + }, []); + + return React.createElement('div', { + className: "mt-12" + }, [ + React.createElement('div', { + key: 'header', + className: "text-center mb-8" + }, [ + React.createElement('h3', { + key: 'title', + className: "text-2xl font-semibold text-primary mb-3" + }, 'Why SecureBit.chat is unique'), + React.createElement('p', { + key: 'subtitle', + className: "text-secondary max-w-2xl mx-auto" + }, 'The only messenger with military-grade cryptography and Lightning payments') + ]), + + React.createElement('div', { + key: 'slider-container', + className: "relative max-w-4xl mx-auto" + }, [ + React.createElement('div', { + key: 'slider-wrapper', + className: "overflow-hidden rounded-xl" + }, [ + React.createElement('div', { + key: 'slides', + className: "flex transition-transform duration-500 ease-in-out", + style: { transform: `translateX(-${currentSlide * 100}%)` } + }, slides.map((slide, index) => + React.createElement('div', { + key: index, + className: "w-full flex-shrink-0 px-4" + }, [ + React.createElement('div', { + key: 'slide-content', + className: "card-minimal rounded-xl p-8 text-center min-h-[300px] flex flex-col justify-center relative overflow-hidden" + }, [ + // Background icon + React.createElement('i', { + key: 'bg-icon', + className: `${slide.icon} absolute right-[-100px] top-1/2 -translate-y-1/2 opacity-10 text-[300px] pointer-events-none ${ + slide.color === 'orange' ? 'text-orange-500' : + slide.color === 'yellow' ? 'text-yellow-500' : + slide.color === 'purple' ? 'text-purple-500' : + slide.color === 'green' ? 'text-green-500' : + slide.color === 'cyan' ? 'text-cyan-500' : + slide.color === 'blue' ? 'text-blue-500' : + 'text-emerald-500' + }` + }), + + // Content + React.createElement('h4', { + key: 'slide-title', + className: "text-xl font-semibold text-primary mb-4 relative z-10" + }, slide.title), + React.createElement('p', { + key: 'slide-description', + className: "text-secondary leading-relaxed max-w-2xl mx-auto relative z-10" + }, slide.description) + ]) + ]) + )) + ]), + + // Navigation + React.createElement('button', { + key: 'prev-btn', + onClick: prevSlide, + className: "absolute left-2 top-1/2 transform -translate-y-1/2 w-10 h-10 bg-gray-600/80 hover:bg-gray-500/80 text-white rounded-full flex items-center justify-center transition-all duration-200 z-10" + }, [ + React.createElement('i', { + key: 'prev-icon', + className: "fas fa-chevron-left" + }) + ]), + React.createElement('button', { + key: 'next-btn', + onClick: nextSlide, + className: "absolute right-2 top-1/2 transform -translate-y-1/2 w-10 h-10 bg-gray-600/80 hover:bg-gray-500/80 text-white rounded-full flex items-center justify-center transition-all duration-200 z-10" + }, [ + React.createElement('i', { + key: 'next-icon', + className: "fas fa-chevron-right" + }) + ]) + ]), + + // Enhanced dots navigation (оставляем улучшенные точки) + React.createElement('div', { + key: 'dots-container', + className: "flex justify-center space-x-3 mt-6" + }, slides.map((slide, index) => + React.createElement('button', { + key: index, + onClick: () => goToSlide(index), + className: `relative group transition-all duration-300 ${ + index === currentSlide + ? 'w-12 h-4 bg-orange-500 rounded-full' + : 'w-4 h-4 bg-gray-600 hover:bg-gray-500 rounded-full hover:scale-125' + }` + }, [ + // Tooltip on hover + React.createElement('div', { + key: 'tooltip', + className: "absolute -top-10 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white text-xs px-2 py-1 rounded opacity-0 group-hover:opacity-100 transition-opacity duration-200 whitespace-nowrap pointer-events-none" + }, slide.title) + ]) + )) + ]); + }; + + + + const ComparisonTable = () => { + const [selectedFeature, setSelectedFeature] = React.useState(null); + + const messengers = [ + { + name: "SecureBit.chat", + logo:
+ +
, + type: "P2P WebRTC", + version: "Latest", + color: "orange", + }, + { + name: "Signal", + logo: ( + + + + + ), + type: "Centralized", + version: "Latest", + color: "blue", + }, + { + name: "Threema", + logo: ( + + + + + + + + ), + type: "Centralized", + version: "Latest", + color: "green", + }, + { + name: "Session", + logo: ( + + + + + ), + type: "Onion Network", + version: "Latest", + color: "cyan", + }, + ]; + + const features = [ + { + name: "Security Architecture", + lockbit: { status: "🏆", detail: "18-layer military-grade defense system with complete ASN.1 validation" }, + signal: { status: "✅", detail: "Signal Protocol with double ratchet" }, + threema: { status: "✅", detail: "Standard security implementation" }, + session: { status: "✅", detail: "Modified Signal Protocol + Onion routing" }, + }, + { + name: "Cryptography", + lockbit: { status: "🏆", detail: "ECDH P-384 + AES-GCM 256 + ECDSA P-384" }, + signal: { status: "✅", detail: "Signal Protocol + Double Ratchet" }, + threema: { status: "✅", detail: "NaCl + XSalsa20 + Poly1305" }, + session: { status: "✅", detail: "Modified Signal Protocol" }, + }, + { + name: "Perfect Forward Secrecy", + lockbit: { status: "🏆", detail: "Auto rotation every 5 minutes or 100 messages" }, + signal: { status: "✅", detail: "Double Ratchet algorithm" }, + threema: { status: "⚠️", detail: "Partial (group chats)" }, + session: { status: "✅", detail: "Session Ratchet algorithm" }, + }, + { + name: "Architecture", + lockbit: { status: "🏆", detail: "Pure P2P WebRTC without servers" }, + signal: { status: "❌", detail: "Centralized Signal servers" }, + threema: { status: "❌", detail: "Threema servers in Switzerland" }, + session: { status: "⚠️", detail: "Onion routing via network nodes" }, + }, + { + name: "Registration Anonymity", + lockbit: { status: "🏆", detail: "No registration required, instant anonymous channels" }, + signal: { status: "❌", detail: "Phone number required" }, + threema: { status: "✅", detail: "ID generated locally" }, + session: { status: "✅", detail: "Random session ID" }, + }, + { + name: "Payment Integration", + lockbit: { status: "🏆", detail: "Lightning Network satoshis per session + WebLN" }, + signal: { status: "❌", detail: "No payment system" }, + threema: { status: "❌", detail: "No payment system" }, + session: { status: "❌", detail: "No payment system" }, + }, + { + name: "Metadata Protection", + lockbit: { status: "🏆", detail: "Full metadata encryption + traffic obfuscation" }, + signal: { status: "⚠️", detail: "Sealed Sender (partial)" }, + threema: { status: "⚠️", detail: "Minimal metadata" }, + session: { status: "✅", detail: "Onion routing hides metadata" }, + }, + { + name: "Traffic Obfuscation", + lockbit: { status: "🏆", detail: "Fake traffic + pattern masking + packet padding" }, + signal: { status: "❌", detail: "No traffic obfuscation" }, + threema: { status: "❌", detail: "No traffic obfuscation" }, + session: { status: "✅", detail: "Onion routing provides obfuscation" }, + }, + { + name: "Open Source", + lockbit: { status: "🏆", detail: "100% open + auditable + MIT license" }, + signal: { status: "✅", detail: "Fully open" }, + threema: { status: "⚠️", detail: "Only clients open" }, + session: { status: "✅", detail: "Fully open" }, + }, + { + name: "MITM Protection", + lockbit: { status: "🏆", detail: "Out-of-band verification + mutual auth + ECDSA" }, + signal: { status: "✅", detail: "Safety numbers verification" }, + threema: { status: "✅", detail: "QR code scanning" }, + session: { status: "⚠️", detail: "Basic key verification" }, + }, + { + name: "Economic Model", + lockbit: { status: "🏆", detail: "Sustainable pay-per-session model" }, + signal: { status: "⚠️", detail: "Donations and grants dependency" }, + threema: { status: "✅", detail: "One-time app purchase" }, + session: { status: "⚠️", detail: "Donations dependency" }, + }, + { + name: "Censorship Resistance", + lockbit: { status: "🏆", detail: "Impossible to block P2P + no servers to target" }, + signal: { status: "⚠️", detail: "Blocked in authoritarian countries" }, + threema: { status: "⚠️", detail: "May be blocked" }, + session: { status: "✅", detail: "Onion routing bypasses blocks" }, + }, + { + name: "Data Storage", + lockbit: { status: "🏆", detail: "Zero data storage - only in browser memory" }, + signal: { status: "⚠️", detail: "Local database storage" }, + threema: { status: "⚠️", detail: "Local + optional backup" }, + session: { status: "⚠️", detail: "Local database storage" }, + }, + { + name: "Key Security", + lockbit: { status: "🏆", detail: "Non-extractable keys + hardware protection" }, + signal: { status: "✅", detail: "Secure key storage" }, + threema: { status: "✅", detail: "Local key storage" }, + session: { status: "✅", detail: "Secure key storage" }, + }, + { + name: "Post-Quantum Roadmap", + lockbit: { status: "✅", detail: "Planned v5.0 - CRYSTALS-Kyber/Dilithium" }, + signal: { status: "⚠️", detail: "PQXDH in development" }, + threema: { status: "❌", detail: "Not announced" }, + session: { status: "❌", detail: "Not announced" }, + }, + ]; + + const getStatusIcon = (status) => { + const statusMap = { + "🏆": { icon: "🏆", color: "text-yellow-400" }, + "✅": { icon: "✅", color: "text-green-400" }, + "⚠️": { icon: "⚠️", color: "text-yellow-400" }, + "❌": { icon: "❌", color: "text-red-400" }, + }; + return statusMap[status] || { icon: status, color: "text-gray-400" }; + }; + + const toggleFeatureDetail = (index) => { + setSelectedFeature(selectedFeature === index ? null : index); + }; + + return ( +
+ {/* Title */} +
+

+ Enhanced Security Edition Comparison +

+

+ Enhanced Security Edition vs leading secure messengers +

+
+ 🏆 + + Category Leader - Military-Grade Security + +
+
+ + {/* Table container */} +
+ {/* Mobile Alert */} +
+

+ 💡 Rotate your device horizontally for better viewing +

+
+ + {/* Table */} +
+ + {/* Table Header */} + + + + {messengers.map((messenger, index) => ( + + ))} + + + + {/* Table body*/} + + {features.map((feature, featureIndex) => ( + + toggleFeatureDetail(featureIndex)} + > + + + + + + + + {/* Details */} + {selectedFeature === featureIndex && ( + + + + + + + + )} + + ))} + +
+ Security Criterion + +
+
{messenger.logo}
+
+ {messenger.name} +
+
{messenger.type}
+
{messenger.version}
+
+
+
+ {feature.name} + +
+
+ + {getStatusIcon(feature.lockbit.status).icon} + + + + {getStatusIcon(feature.signal.status).icon} + + + + {getStatusIcon(feature.threema.status).icon} + + + + {getStatusIcon(feature.session.status).icon} + +
Technical Details: +
+ {feature.lockbit.detail} +
+
+
+ {feature.signal.detail} +
+
+
+ {feature.threema.detail} +
+
+
+ {feature.session.detail} +
+
+
+ + {/* Legend */} +
+
+ 🏆 + Category Leader +
+
+ + Excellent +
+
+ ⚠️ + Partial/Limited +
+
+ + Not Available +
+
+ + {/* Legend */} +
+
+

+ + SecureBit.chat Enhanced Security Edition Summary +

+

+ SecureBit.chat dominates in 11 out of 15 security categories, establishing itself as the most secure P2P messenger available. + The Enhanced Security Edition introduces revolutionary 18-layer defense architecture with complete ASN.1 validation, Lightning Network integration, and military-grade cryptography that exceeds government and enterprise standards. +

+
+
+
🔐 Cryptographic Superiority
+

+ ECDH P-384 + AES-GCM 256 + ECDSA P-384 + Complete ASN.1 Validation with non-extractable keys and 18-layer defense system +

+
+
+
⚡ Lightning Integration
+

+ First messenger with Lightning Network payments - sustainable economic model with instant satoshi transactions +

+
+
+
🌐 True P2P Architecture
+

+ Pure WebRTC connections with zero servers, impossible to censor or shutdown, complete anonymity +

+
+
+
🎭 Traffic Obfuscation
+

+ Advanced fake traffic generation, packet padding, and pattern masking defeat traffic analysis +

+
+
+
+
+ + {/* Version information */} +
+
+ 🚀 + Enhanced Security Edition v4.02.985 - ECDH + DTLS + SAS - + Active Production Release + | Next: v5.0 Post-Quantum +
+
+
+
+ ); + }; + + function Roadmap() { + const [selectedPhase, setSelectedPhase] = React.useState(null); + const phases = [ + { + version: "v1.0", + title: "Start of Development", + status: "done", + date: "Early 2025", + description: "Idea, prototype, and infrastructure setup", + features: [ + "Concept and requirements formation", + "Stack selection: WebRTC, P2P, cryptography", + "First messaging prototypes", + "Repository creation and CI", + "Basic encryption architecture", + "UX/UI design" + ] + }, + { + version: "v1.5", + title: "Alpha Release", + status: "done", + date: "Spring 2025", + description: "First public alpha: basic chat and key exchange", + features: [ + "Basic P2P messaging via WebRTC", + "Simple E2E encryption (demo scheme)", + "Stable signaling and reconnection", + "Minimal UX for testing", + "Feedback collection from early testers" + ] + }, + { + version: "v2.0", + title: "Security Hardened", + status: "done", + date: "Summer 2025", + description: "Security strengthening and stable branch release", + features: [ + "ECDH/ECDSA implementation in production", + "Perfect Forward Secrecy and key rotation", + "Improved authentication checks", + "File encryption and large payload transfers", + "Audit of basic cryptoprocesses" + ] + }, + { + version: "v3.0", + title: "Scaling & Stability", + status: "done", + date: "Fall 2025", + description: "Network scaling and stability improvements", + features: [ + "Optimization of P2P connections and NAT traversal", + "Reconnection mechanisms and message queues", + "Reduced battery consumption on mobile", + "Support for multi-device synchronization", + "Monitoring and logging tools for developers" + ] + }, + { + version: "v3.5", + title: "Privacy-first Release", + status: "done", + date: "Winter 2025", + description: "Focus on privacy: minimizing metadata", + features: [ + "Metadata protection and fingerprint reduction", + "Experiments with onion routing and DHT", + "Options for anonymous connections", + "Preparation for open code audit", + "Improved user verification processes" + ] + }, + + // current and future phases + { + version: "v4.02.985", + title: "Enhanced Security Edition", + status: "current", + date: "Now", + description: "Current version with ECDH + DTLS + SAS security, 18-layer military-grade cryptography and complete ASN.1 validation", + features: [ + "ECDH + DTLS + SAS triple-layer security", + "ECDH P-384 + AES-GCM 256-bit encryption", + "DTLS fingerprint verification", + "SAS (Short Authentication String) verification", + "Perfect Forward Secrecy with key rotation", + "Enhanced MITM attack prevention", + "Complete ASN.1 DER validation", + "OID and EC point verification", + "SPKI structure validation", + "Lightning Network payments", + "P2P WebRTC architecture", + "Metadata protection", + "100% open source code" + ] + }, + { + version: "v4.5", + title: "Mobile & Desktop Edition", + status: "development", + date: "Q2 2025", + description: "Native apps for all platforms", + features: [ + "PWA app for mobile", + "Electron app for desktop", + "Real-time notifications", + "Automatic reconnection", + "Battery optimization", + "Cross-device synchronization", + "Improved UX/UI", + "Support for files up to 100MB" + ] + }, + { + version: "v5.0", + title: "Quantum-Resistant Edition", + status: "planned", + date: "Q4 2025", + description: "Protection against quantum computers", + features: [ + "Post-quantum cryptography CRYSTALS-Kyber", + "SPHINCS+ digital signatures", + "Hybrid scheme: classic + PQ", + "Quantum-safe key exchange", + "Updated hashing algorithms", + "Migration of existing sessions", + "Compatibility with v4.x", + "Quantum-resistant protocols" + ] + }, + { + version: "v5.5", + title: "Group Communications", + status: "planned", + date: "Q2 2026", + description: "Group chats with preserved privacy", + features: [ + "P2P group connections up to 8 participants", + "Mesh networking for groups", + "Signal Double Ratchet for groups", + "Anonymous groups without metadata", + "Ephemeral groups (disappear after session)", + "Group Lightning payments", + "Cryptographic group administration", + "Group member auditing" + ] + }, + { + version: "v6.0", + title: "Decentralized Network", + status: "research", + date: "2027", + description: "Fully decentralized network", + features: [ + "LockBit node mesh network", + "DHT for peer discovery", + "Built-in onion routing", + "Tokenomics and node incentives", + "Governance via DAO", + "Interoperability with other networks", + "Cross-platform compatibility", + "Self-healing network" + ] + }, + { + version: "v7.0", + title: "AI Privacy Assistant", + status: "research", + date: "2028+", + description: "AI for privacy and security", + features: [ + "Local AI threat analysis", + "Automatic MITM detection", + "Adaptive cryptography", + "Personalized security recommendations", + "Zero-knowledge machine learning", + "Private AI assistant", + "Predictive security", + "Autonomous attack protection" + ] + } + ]; + + + const getStatusConfig = (status) => { + switch (status) { + case 'current': + return { + color: 'green', + bgClass: 'bg-green-500/10 border-green-500/20', + textClass: 'text-green-400', + icon: 'fas fa-check-circle', + label: 'Current Version' + }; + case 'development': + return { + color: 'orange', + bgClass: 'bg-orange-500/10 border-orange-500/20', + textClass: 'text-orange-400', + icon: 'fas fa-code', + label: 'In Development' + }; + case 'planned': + return { + color: 'blue', + bgClass: 'bg-blue-500/10 border-blue-500/20', + textClass: 'text-blue-400', + icon: 'fas fa-calendar-alt', + label: 'Planned' + }; + case 'research': + return { + color: 'purple', + bgClass: 'bg-purple-500/10 border-purple-500/20', + textClass: 'text-purple-400', + icon: 'fas fa-flask', + label: 'Research' + }; + case 'done': + return { + color: 'gray', + bgClass: 'bg-gray-500/10 border-gray-500/20', + textClass: 'text-gray-300', + icon: 'fas fa-flag-checkered', + label: 'Released' + }; + default: + return { + color: 'gray', + bgClass: 'bg-gray-500/10 border-gray-500/20', + textClass: 'text-gray-400', + icon: 'fas fa-question', + label: 'Unknown' + }; + } + }; + + + const togglePhaseDetail = (index) => { + setSelectedPhase(selectedPhase === index ? null : index); + }; + return ( +
+
+

+ Development Roadmap +

+

+ Evolution of SecureBit.chat : from initial development to quantum-resistant decentralized network with complete ASN.1 validation +

+
+ + + Click on a version for details + +
+
+ +
+
+ {/* The line has been removed */} + +
+ {phases.map((phase, index) => { + const statusConfig = getStatusConfig(phase.status); + const isExpanded = selectedPhase === index; + + return ( +
+ {/* The dots are visible only on sm and larger screens */} + + +
+ ); + })} +
+
+
+ +
+
+

+ Join the future of privacy +

+

+ SecureBit.chat grows thanks to the community. Your ideas and feedback help shape the future of secure communication with complete ASN.1 validation. +

+ + +
+
+
+ ); + } + + + // Enhanced Copy Button with better UX + const EnhancedCopyButton = ({ text, className = "", children }) => { + const [copied, setCopied] = React.useState(false); + + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(text); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (error) { + console.error('Copy failed:', error); + // Fallback for older browsers + const textArea = document.createElement('textarea'); + textArea.value = text; + document.body.appendChild(textArea); + textArea.select(); + document.execCommand('copy'); + document.body.removeChild(textArea); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } + }; + + return React.createElement('button', { + onClick: handleCopy, + className: `${className} transition-all duration-200` + }, [ + React.createElement('i', { + key: 'icon', + className: `${copied ? 'fas fa-check accent-green' : 'fas fa-copy text-secondary'} mr-2` + }), + copied ? 'Copied!' : children + ]); + }; + + // Verification Component + const VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, remoteConfirmed, bothConfirmed }) => { + return React.createElement('div', { + className: "card-minimal rounded-xl p-6 border-purple-500/20" + }, [ + React.createElement('div', { + key: 'header', + className: "flex items-center mb-4" + }, [ + React.createElement('div', { + key: 'icon', + className: "w-10 h-10 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mr-3" + }, [ + React.createElement('i', { + className: 'fas fa-shield-alt accent-purple' + }) + ]), + React.createElement('h3', { + key: 'title', + className: "text-lg font-medium text-primary" + }, "Security verification") + ]), + React.createElement('div', { + key: 'content', + className: "space-y-4" + }, [ + React.createElement('p', { + key: 'description', + className: "text-secondary text-sm" + }, "Verify the security code with your contact via another communication channel (voice, SMS, etc.):"), + React.createElement('div', { + key: 'code-display', + className: "text-center" + }, [ + React.createElement('div', { + key: 'code', + className: "verification-code text-2xl py-4" + }, verificationCode) + ]), + // Verification status indicators + React.createElement('div', { + key: 'verification-status', + className: "space-y-2" + }, [ + React.createElement('div', { + key: 'local-status', + className: `flex items-center justify-between p-2 rounded-lg ${localConfirmed ? 'bg-green-500/10 border border-green-500/20' : 'bg-gray-500/10 border border-gray-500/20'}` + }, [ + React.createElement('span', { + key: 'local-label', + className: "text-sm text-secondary" + }, "Your confirmation:"), + React.createElement('div', { + key: 'local-indicator', + className: "flex items-center" + }, [ + React.createElement('i', { + key: 'local-icon', + className: `fas ${localConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2` + }), + React.createElement('span', { + key: 'local-text', + className: `text-sm ${localConfirmed ? 'text-green-400' : 'text-gray-400'}` + }, localConfirmed ? 'Confirmed' : 'Pending') + ]) + ]), + React.createElement('div', { + key: 'remote-status', + className: `flex items-center justify-between p-2 rounded-lg ${remoteConfirmed ? 'bg-green-500/10 border border-green-500/20' : 'bg-gray-500/10 border border-gray-500/20'}` + }, [ + React.createElement('span', { + key: 'remote-label', + className: "text-sm text-secondary" + }, "Peer confirmation:"), + React.createElement('div', { + key: 'remote-indicator', + className: "flex items-center" + }, [ + React.createElement('i', { + key: 'remote-icon', + className: `fas ${remoteConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2` + }), + React.createElement('span', { + key: 'remote-text', + className: `text-sm ${remoteConfirmed ? 'text-green-400' : 'text-gray-400'}` + }, remoteConfirmed ? 'Confirmed' : 'Pending') + ]) + ]) + ]), + React.createElement('div', { + key: 'warning', + className: "p-3 bg-yellow-500/10 border border-yellow-500/20 rounded-lg" + }, [ + React.createElement('p', { + className: "text-yellow-400 text-sm flex items-center" + }, [ + React.createElement('i', { + className: 'fas fa-exclamation-triangle mr-2' + }), + 'Make sure the codes match exactly.!' + ]) + ]), + React.createElement('div', { + key: 'buttons', + className: "flex space-x-3" + }, [ + React.createElement('button', { + key: 'confirm', + onClick: onConfirm, + disabled: localConfirmed, + className: `flex-1 py-3 px-4 rounded-lg font-medium transition-all duration-200 ${localConfirmed ? 'bg-gray-500/20 text-gray-400 cursor-not-allowed' : 'btn-verify text-white'}` + }, [ + React.createElement('i', { + className: `fas ${localConfirmed ? 'fa-check-circle' : 'fa-check'} mr-2` + }), + localConfirmed ? 'Confirmed' : 'The codes match' + ]), + React.createElement('button', { + key: 'reject', + onClick: onReject, + className: "flex-1 bg-red-500/10 hover:bg-red-500/20 text-red-400 border border-red-500/20 py-3 px-4 rounded-lg font-medium transition-all duration-200" + }, [ + React.createElement('i', { + className: 'fas fa-times mr-2' + }), + 'The codes do not match' + ]) + ]) + ]) + ]); + }; + + // Enhanced Chat Message with better security indicators + const EnhancedChatMessage = ({ message, type, timestamp }) => { + const formatTime = (ts) => { + return new Date(ts).toLocaleTimeString('ru-RU', { + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }); + }; + + const getMessageStyle = () => { + switch (type) { + case 'sent': + return { + container: "ml-auto bg-orange-500/15 border-orange-500/20 text-primary", + icon: "fas fa-lock accent-orange", + label: "Encrypted" + }; + case 'received': + return { + container: "mr-auto card-minimal text-primary", + icon: "fas fa-unlock-alt accent-green", + label: "Decrypted" + }; + case 'system': + return { + container: "mx-auto bg-yellow-500/10 border border-yellow-500/20 text-yellow-400", + icon: "fas fa-info-circle accent-yellow", + label: "System" + }; + default: + return { + container: "mx-auto card-minimal text-secondary", + icon: "fas fa-circle text-muted", + label: "Unknown" + }; + } + }; + + const style = getMessageStyle(); + + return React.createElement('div', { + className: `message-slide mb-3 p-3 rounded-lg max-w-md break-words ${style.container} border` + }, [ + React.createElement('div', { + key: 'content', + className: "flex items-start space-x-2" + }, [ + React.createElement('i', { + key: 'icon', + className: `${style.icon} text-sm mt-0.5 opacity-70` + }), + React.createElement('div', { + key: 'text', + className: "flex-1" + }, [ + React.createElement('div', { + key: 'message', + className: "text-sm" + }, message), + timestamp && React.createElement('div', { + key: 'meta', + className: "flex items-center justify-between mt-1 text-xs opacity-50" + }, [ + React.createElement('span', { + key: 'time' + }, formatTime(timestamp)), + React.createElement('span', { + key: 'status', + className: "text-xs" + }, style.label) + ]) + ]) + ]) + ]); + }; + + // Enhanced Connection Setup with verification + const EnhancedConnectionSetup = ({ + messages, + onCreateOffer, + onCreateAnswer, + onConnect, + onClearData, + onVerifyConnection, + connectionStatus, + offerData, + answerData, + offerInput, + setOfferInput, + answerInput, + setAnswerInput, + showOfferStep, + showAnswerStep, + verificationCode, + showVerification, + offerPassword, + answerPassword, + localVerificationConfirmed, + remoteVerificationConfirmed, + bothVerificationsConfirmed + }) => { + const [mode, setMode] = React.useState('select'); + + const resetToSelect = () => { + setMode('select'); + onClearData(); + }; + + const handleVerificationConfirm = () => { + onVerifyConnection(true); + }; + + const handleVerificationReject = () => { + onVerifyConnection(false); + }; + + if (showVerification) { + return React.createElement('div', { + className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" + }, [ + React.createElement('div', { + key: 'verification', + className: "w-full max-w-md" + }, [ + React.createElement(VerificationStep, { + verificationCode: verificationCode, + onConfirm: handleVerificationConfirm, + onReject: handleVerificationReject, + localConfirmed: localVerificationConfirmed, + remoteConfirmed: remoteVerificationConfirmed, + bothConfirmed: bothVerificationsConfirmed + }) + ]) + ]); + } + + if (mode === 'select') { + return React.createElement('div', { + className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" + }, [ + React.createElement('div', { + key: 'selector', + className: "w-full max-w-4xl" + }, [ + React.createElement('div', { + key: 'header', + className: "text-center mb-8" + }, [ + React.createElement('h2', { + key: 'title', + className: "text-2xl font-semibold text-primary mb-3" + }, 'Start secure communication'), + React.createElement('p', { + key: 'subtitle', + className: "text-secondary max-w-2xl mx-auto" + }, "Choose a connection method for a secure channel with ECDH encryption and Perfect Forward Secrecy.") + ]), + + React.createElement('div', { + key: 'options', + className: "grid md:grid-cols-2 gap-6 max-w-3xl mx-auto" + }, [ + // Create Connection + React.createElement('div', { + key: 'create', + onClick: () => setMode('create'), + className: "card-minimal rounded-xl p-6 cursor-pointer group" + }, [ + React.createElement('div', { + key: 'icon', + className: "w-12 h-12 bg-blue-500/10 border border-blue-500/20 rounded-lg flex items-center justify-center mx-auto mb-4" + }, [ + React.createElement('i', { + className: 'fas fa-plus text-xl text-blue-400' + }) + ]), + React.createElement('h3', { + key: 'title', + className: "text-lg font-semibold text-primary text-center mb-3" + }, "Create channel"), + React.createElement('p', { + key: 'description', + className: "text-secondary text-center text-sm mb-4" + }, "Initiate a new secure connection with encrypted exchange"), + React.createElement('div', { + key: 'features', + className: "space-y-2" + }, [ + React.createElement('div', { + key: 'f1', + className: "flex items-center text-sm text-muted" + }, [ + React.createElement('i', { + className: 'fas fa-key accent-orange mr-2 text-xs' + }), + 'Generating ECDH keys' + ]), + React.createElement('div', { + key: 'f2', + className: "flex items-center text-sm text-muted" + }, [ + React.createElement('i', { + className: 'fas fa-shield-alt accent-orange mr-2 text-xs' + }), + 'Verification code' + ]), + React.createElement('div', { + key: 'f3', + className: "flex items-center text-sm text-muted" + }, [ + React.createElement('i', { + className: 'fas fa-sync-alt accent-purple mr-2 text-xs' + }), + 'PFS key rotation' + ]) + ]) + ]), + + // Join Connection + React.createElement('div', { + key: 'join', + onClick: () => setMode('join'), + className: "card-minimal rounded-xl p-6 cursor-pointer group" + }, [ + React.createElement('div', { + key: 'icon', + className: "w-12 h-12 bg-green-500/10 border border-green-500/20 rounded-lg flex items-center justify-center mx-auto mb-4" + }, [ + React.createElement('i', { + className: 'fas fa-link text-xl accent-green' + }) + ]), + React.createElement('h3', { + key: 'title', + className: "text-lg font-semibold text-primary text-center mb-3" + }, "Join"), + React.createElement('p', { + key: 'description', + className: "text-secondary text-center text-sm mb-4" + }, "Connect to an existing secure channel"), + React.createElement('div', { + key: 'features', + className: "space-y-2" + }, [ + React.createElement('div', { + key: 'f1', + className: "flex items-center text-sm text-muted" + }, [ + React.createElement('i', { + className: 'fas fa-paste accent-green mr-2 text-xs' + }), + 'Paste Offer invitation' + ]), + React.createElement('div', { + key: 'f2', + className: "flex items-center text-sm text-muted" + }, [ + React.createElement('i', { + className: 'fas fa-check-circle accent-green mr-2 text-xs' + }), + 'Automatic verification' + ]), + React.createElement('div', { + key: 'f3', + className: "flex items-center text-sm text-muted" + }, [ + React.createElement('i', { + className: 'fas fa-sync-alt accent-purple mr-2 text-xs' + }), + 'PFS protection' + ]) + ]) + ]) + ]), + + + React.createElement('div', { + key: 'security-features', + className: "grid grid-cols-2 md:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4 max-w-6xl mx-auto mt-8" + }, [ + React.createElement('div', { key: 'feature1', className: "text-center p-3 sm:p-4" }, [ + React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-green-500/10 border border-green-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement('i', { className: 'fas fa-key accent-green' }) + ]), + React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "ECDH P-384 Key Exchange"), + React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Military-grade elliptic curve key exchange") + ]), + React.createElement('div', { key: 'feature2', className: "text-center p-3 sm:p-4" }, [ + React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement('i', { className: 'fas fa-user-shield accent-purple' }) + ]), + React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "MITM Protection"), + React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Out-of-band verification against attacks") + ]), + React.createElement('div', { key: 'feature3', className: "text-center p-3 sm:p-4" }, [ + React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-orange-500/10 border border-orange-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement('i', { className: 'fas fa-lock accent-orange' }) + ]), + React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "AES-GCM 256 Encryption"), + React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Authenticated encryption standard") + ]), + React.createElement('div', { key: 'feature4', className: "text-center p-3 sm:p-4" }, [ + React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-cyan-500/10 border border-cyan-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement('i', { className: 'fas fa-sync-alt accent-cyan' }) + ]), + React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "Perfect Forward Secrecy"), + React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Automatic key rotation every 5 minutes") + ]), + React.createElement('div', { key: 'feature5', className: "text-center p-3 sm:p-4" }, [ + React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-blue-500/10 border border-blue-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement('i', { className: 'fas fa-signature accent-blue' }) + ]), + React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "ECDSA P-384 Signatures"), + React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Digital signatures for message integrity") + ]), + React.createElement('div', { key: 'feature6', className: "text-center p-3 sm:p-4" }, [ + React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 bg-yellow-500/10 border border-yellow-500/20 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [ + React.createElement('i', { className: 'fas fa-bolt accent-yellow' }) + ]), + React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "Lightning Payments"), + React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Pay-per-session via WebLN") + ]) + ]), + + // Wallet Logos Section + React.createElement('div', { + key: 'wallet-logos-section', + className: "mt-8" + }, [ + React.createElement('div', { + key: 'wallet-logos-header', + className: "text-center mb-4" + }, [ + React.createElement('h3', { + key: 'title', + className: "text-lg font-medium text-primary mb-2" + }, "Supported Lightning wallets"), + React.createElement('p', { + key: 'subtitle', + className: "text-secondary text-sm" + }, "To pay for sessions, use any of the popular wallets.") + ]), + React.createElement('div', { + key: 'wallet-logos-container', + className: "wallet-logos-container" + }, [ + React.createElement('div', { + key: 'wallet-logos-track', + className: "wallet-logos-track" + }, [ + // First set of logos + React.createElement('a', { + key: 'alby1-link', + href: "https://getalby.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo alby" + }, [ + React.createElement('img', { + key: 'alby-img1', + src: "logo/alby.svg", + alt: "Alby Lightning Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'zeus1-link', + href: "https://zeusln.app", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo zeus" + }, [ + React.createElement('img', { + key: 'zeus-img1', + src: "logo/zeus.svg", + alt: "Zeus Lightning Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'wos1-link', + href: "https://www.walletofsatoshi.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo wos" + }, [ + React.createElement('img', { + key: 'wos-img1', + src: "logo/wos.svg", + alt: "Wallet of Satoshi", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'muun1-link', + href: "https://muun.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo muun" + }, [ + React.createElement('img', { + key: 'muun-img1', + src: "logo/muun.svg", + alt: "Muun Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'atomic1-link', + href: "https://atomicwallet.io", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo atomic" + }, [ + React.createElement('img', { + key: 'atomic-img1', + src: "logo/atomic.svg", + alt: "Atomic Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'breez1-link', + href: "https://breez.technology/mobile/", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo breez" + }, [ + React.createElement('img', { + key: 'breez-img1', + src: "logo/breez.svg", + alt: "Breez Lightning Wallet", + }) + ]), + React.createElement('a', { + key: 'lightning-labs1-link', + href: "https://lightning.engineering", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo lightning-labs" + }, [ + React.createElement('img', { + key: 'lightning-labs-img1', + src: "logo/lightning-labs.svg", + alt: "Lightning Labs", + }) + ]), + React.createElement('a', { + key: 'lnbits1-link', + href: "https://lnbits.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo lnbits" + }, [ + React.createElement('img', { + key: 'lnbits-img1', + src: "logo/lnbits.svg", + alt: "LNbits", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'strike1-link', + href: "https://strike.me", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo strike" + }, [ + React.createElement('img', { + key: 'strike-img1', + src: "logo/strike.svg", + alt: "Strike", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'impervious1-link', + href: "https://impervious.ai", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo impervious" + }, [ + React.createElement('img', { + key: 'impervious-img1', + src: "logo/impervious.svg", + alt: "Impervious", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'bitcoin-lightning1-link', + href: "https://www.blink.sv/", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo bitcoin-lightning" + }, [ + React.createElement('img', { + key: 'blink-img1', + src: "logo/blink.svg", + alt: "Blink Wallet", + className: "wallet-logo-img" + }) + ]), + // Second set of logos + React.createElement('a', { + key: 'alby2-link', + href: "https://getalby.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo alby" + }, [ + React.createElement('img', { + key: 'alby-img2', + src: "logo/alby.svg", + alt: "Alby Lightning Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'zeus2-link', + href: "https://zeusln.app", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo zeus" + }, [ + React.createElement('img', { + key: 'zeus-img2', + src: "logo/zeus.svg", + alt: "Zeus Lightning Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'wos2-link', + href: "https://www.walletofsatoshi.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo wos" + }, [ + React.createElement('img', { + key: 'wos-img2', + src: "logo/wos.svg", + alt: "Wallet of Satoshi", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'muun2-link', + href: "https://muun.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo muun" + }, [ + React.createElement('img', { + key: 'muun-img2', + src: "logo/muun.svg", + alt: "Muun Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'atomic2-link', + href: "https://atomicwallet.io", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo atomic" + }, [ + React.createElement('img', { + key: 'atomic-img2', + src: "logo/atomic.svg", + alt: "Atomic Wallet", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'breez2-link', + href: "https://breez.technology/mobile/", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo breez" + }, [ + React.createElement('img', { + key: 'breez-img2', + src: "logo/breez.svg", + alt: "Breez Lightning Wallet", + }) + ]), + React.createElement('a', { + key: 'lightning-labs2-link', + href: "https://lightning.engineering", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo lightning-labs" + }, [ + React.createElement('img', { + key: 'lightning-labs-img2', + src: "logo/lightning-labs.svg", + alt: "Lightning Labs", + }) + ]), + React.createElement('a', { + key: 'lnbits2-link', + href: "https://lnbits.com", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo lnbits" + }, [ + React.createElement('img', { + key: 'lnbits-img2', + src: "logo/lnbits.svg", + alt: "LNbits", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'strike2-link', + href: "https://strike.me", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo strike" + }, [ + React.createElement('img', { + key: 'strike-img2', + src: "logo/strike.svg", + alt: "Strike", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'impervious2-link', + href: "https://impervious.ai", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo impervious" + }, [ + React.createElement('img', { + key: 'impervious-img2', + src: "logo/impervious.svg", + alt: "Impervious", + className: "wallet-logo-img" + }) + ]), + React.createElement('a', { + key: 'bitcoin-lightning2-link', + href: "https://www.blink.sv/", + target: "_blank", + rel: "noindex nofollow", + className: "wallet-logo bitcoin-lightning" + }, [ + React.createElement('img', { + key: 'blink-img2', + src: "logo/blink.svg", + alt: "Blink Wallet", + className: "wallet-logo-img" + }) + ]) + ]) + ]) + ]), + React.createElement(UniqueFeatureSlider, { key: 'unique-features-slider' }), + + React.createElement(DownloadApps, { key: 'download-apps' }), + + React.createElement(ComparisonTable, { key: 'comparison-table' }), + + React.createElement(Roadmap, { key: 'roadmap' }), + ]) + ]); + } + + if (mode === 'create') { + return React.createElement('div', { + className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" + }, [ + React.createElement('div', { + key: 'create-flow', + className: "w-full max-w-3xl space-y-6" + }, [ + React.createElement('div', { + key: 'header', + className: "text-center" + }, [ + React.createElement('button', { + key: 'back', + onClick: resetToSelect, + className: "mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm" + }, [ + React.createElement('i', { + className: 'fas fa-arrow-left mr-2' + }), + 'Back to selection' + ]), + React.createElement('h2', { + key: 'title', + className: "text-xl font-semibold text-primary mb-2" + }, 'Creating a secure channel') + ]), + + // Step 1 + React.createElement('div', { + key: 'step1', + className: "card-minimal rounded-xl p-6" + }, [ + React.createElement('div', { + key: 'step-header', + className: "flex items-center mb-4" + }, [ + React.createElement('div', { + key: 'number', + className: "step-number mr-3" + }, '1'), + React.createElement('h3', { + key: 'title', + className: "text-lg font-medium text-primary" + }, "Generating ECDH keys and verification code") + ]), + React.createElement('p', { + key: 'description', + className: "text-secondary text-sm mb-4" + }, "Creating cryptographically strong keys and codes to protect against attacks"), + React.createElement('button', { + key: 'create-btn', + onClick: onCreateOffer, + disabled: connectionStatus === 'connecting' || showOfferStep, + className: `w-full btn-primary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed` + }, [ + React.createElement('i', { + className: 'fas fa-shield-alt mr-2' + }), + showOfferStep ? 'Keys created ✓' : 'Create secure keys' + ]), + + showOfferStep && React.createElement('div', { + key: 'offer-result', + className: "mt-6 space-y-4" + }, [ + React.createElement('div', { + key: 'success', + className: "p-3 bg-green-500/10 border border-green-500/20 rounded-lg" + }, [ + React.createElement('p', { + className: "text-green-400 text-sm font-medium flex items-center" + }, [ + React.createElement('i', { + className: 'fas fa-check-circle mr-2' + }), + 'Secure invitation created! Send the code to your contact:' + ]) + ]), + React.createElement('div', { + key: 'offer-data', + className: "space-y-3" + }, [ + React.createElement('textarea', { + key: 'textarea', + value: typeof offerData === 'object' ? JSON.stringify(offerData, null, 2) : offerData, + readOnly: true, + rows: 8, + className: "w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg font-mono text-xs text-secondary resize-none custom-scrollbar" + }), + React.createElement(EnhancedCopyButton, { + key: 'copy', + text: typeof offerData === 'object' ? JSON.stringify(offerData, null, 2) : offerData, + className: "w-full px-3 py-2 bg-orange-500/10 hover:bg-orange-500/20 text-orange-400 border border-orange-500/20 rounded text-sm font-medium" + }, 'Copy invitation code') + ]) + ]) + ]), + + // Step 2 - Session Type Selection + // showOfferStep && React.createElement('div', { + // key: 'step2', + // className: "card-minimal rounded-xl p-6" + // }, [ + // React.createElement('div', { + // key: 'step-header', + // className: "flex items-center mb-4" + // }, [ + // React.createElement('div', { + // key: 'number', + // className: "w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3" + // }, '2'), + // React.createElement('h3', { + // key: 'title', + // className: "text-lg font-medium text-primary" + // }, "Select session type") + // ]), + // React.createElement('p', { + // key: 'description', + // className: "text-secondary text-sm mb-4" + // }, "Choose a session plan or use limited demo mode for testing."), + // React.createElement(SessionTypeSelector, { + // key: 'session-selector', + // onSelectType: (sessionType) => { + // // Save the selected session type + // setSelectedSessionType(sessionType); + // console.log('🎯 Session type selected:', sessionType); + + // // FIX: For demo sessions, we immediately call automatic activation + // if (sessionType === 'demo') { + // console.log('🎮 Demo session selected, scheduling automatic activation...'); + // // Delay activation for 2 seconds to stabilize + // setTimeout(() => { + // if (sessionManager) { + // console.log('🚀 Triggering demo session activation from selection...'); + // handleDemoVerification(); + // } + // }, 2000); + // } + + // // Open a modal payment window + // if (typeof window.showPaymentModal === 'function') { + // window.showPaymentModal(sessionType); + // } else { + // // Fallback - show session information + // console.log('Selected session type:', sessionType); + // } + // }, + // onCancel: resetToSelect, + // sessionManager: window.sessionManager + // }) + // ]), + + // Step 3 - Waiting for response + showOfferStep && React.createElement('div', { + key: 'step2', + className: "card-minimal rounded-xl p-6" + }, [ + React.createElement('div', { + key: 'step-header', + className: "flex items-center mb-4" + }, [ + React.createElement('div', { + key: 'number', + className: "w-8 h-8 bg-blue-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3" + }, '2'), + React.createElement('h3', { + key: 'title', + className: "text-lg font-medium text-primary" + }, "Waiting for the peer's response") + ]), + React.createElement('p', { + key: 'description', + className: "text-secondary text-sm mb-4" + }, "Paste the encrypted invitation code from your contact."), + React.createElement('textarea', { + key: 'input', + value: answerInput, + onChange: (e) => setAnswerInput(e.target.value), + rows: 6, + placeholder: "Paste the encrypted response code from your contact...", + className: "w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-orange-500/40 focus:outline-none transition-all custom-scrollbar text-sm" + }), + React.createElement('button', { + key: 'connect-btn', + onClick: onConnect, + disabled: !answerInput.trim(), + className: "w-full btn-secondary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" + }, [ + React.createElement('i', { + className: 'fas fa-rocket mr-2' + }), + 'Establish connection' + ]) + ]) + ]) + ]); + } + + if (mode === 'join') { + return React.createElement('div', { + className: "min-h-[calc(100vh-104px)] flex items-center justify-center p-4" + }, [ + React.createElement('div', { + key: 'join-flow', + className: "w-full max-w-3xl space-y-6" + }, [ + React.createElement('div', { + key: 'header', + className: "text-center" + }, [ + React.createElement('button', { + key: 'back', + onClick: resetToSelect, + className: "mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm" + }, [ + React.createElement('i', { + className: 'fas fa-arrow-left mr-2' + }), + 'Back to selection' + ]), + React.createElement('h2', { + key: 'title', + className: "text-xl font-semibold text-primary mb-2" + }, 'Joining the secure channel') + ]), + + // Step 1 + React.createElement('div', { + key: 'step1', + className: "card-minimal rounded-xl p-6" + }, [ + React.createElement('div', { + key: 'step-header', + className: "flex items-center mb-4" + }, [ + React.createElement('div', { + key: 'number', + className: "w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3" + }, '1'), + React.createElement('h3', { + key: 'title', + className: "text-lg font-medium text-primary" + }, "Paste secure invitation") + ]), + React.createElement('p', { + key: 'description', + className: "text-secondary text-sm mb-4" + }, "Copy and paste the encrypted invitation code from the initiator."), + React.createElement('textarea', { + key: 'input', + value: offerInput, + onChange: (e) => setOfferInput(e.target.value), + rows: 8, + placeholder: "Paste the encrypted invitation code...", + className: "w-full p-3 bg-custom-bg border border-gray-500/20 rounded-lg resize-none mb-4 text-secondary placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm" + }), + React.createElement('button', { + key: 'process-btn', + onClick: onCreateAnswer, + disabled: !offerInput.trim() || connectionStatus === 'connecting', + className: "w-full btn-secondary text-white py-3 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed" + }, [ + React.createElement('i', { + className: 'fas fa-cogs mr-2' + }), + 'Process the invitation' + ]) + ]), + + // Step 2 + showAnswerStep && React.createElement('div', { + key: 'step2', + className: "card-minimal rounded-xl p-6" + }, [ + React.createElement('div', { + key: 'step-header', + className: "flex items-center mb-4" + }, [ + React.createElement('div', { + key: 'number', + className: "step-number mr-3" + }, '2'), + React.createElement('h3', { + key: 'title', + className: "text-lg font-medium text-primary" + }, "Sending a secure response") + ]), + React.createElement('div', { + key: 'success', + className: "p-3 bg-green-500/10 border border-green-500/20 rounded-lg mb-4" + }, [ + React.createElement('p', { + className: "text-green-400 text-sm font-medium flex items-center" + }, [ + React.createElement('i', { + className: 'fas fa-check-circle mr-2' + }), + 'Secure response created! Send this code to the initiator:' + ]) + ]), + React.createElement('div', { + key: 'answer-data', + className: "space-y-3 mb-4" + }, [ + React.createElement('textarea', { + key: 'textarea', + value: typeof answerData === 'object' ? JSON.stringify(answerData, null, 2) : answerData, + readOnly: true, + rows: 6, + className: "w-full p-3 bg-custom-bg border border-green-500/20 rounded-lg font-mono text-xs text-secondary resize-none custom-scrollbar" + }), + React.createElement(EnhancedCopyButton, { + key: 'copy', + text: typeof answerData === 'object' ? JSON.stringify(answerData, null, 2) : answerData, + className: "w-full px-3 py-2 bg-green-500/10 hover:bg-green-500/20 text-green-400 border border-green-500/20 rounded text-sm font-medium" + }, 'Copy response code') + ]), + React.createElement('div', { + key: 'info', + className: "p-3 bg-purple-500/10 border border-purple-500/20 rounded-lg" + }, [ + React.createElement('p', { + className: "text-purple-400 text-sm flex items-center justify-center" + }, [ + React.createElement('i', { + className: 'fas fa-shield-alt mr-2' + }), + 'The connection will be established with verification' + ]) + ]) + ]) + ]) + ]); + } + }; + + const EnhancedChatInterface = ({ + messages, + messageInput, + setMessageInput, + onSendMessage, + onDisconnect, + keyFingerprint, + isVerified, + chatMessagesRef, + scrollToBottom, + webrtcManager + }) => { + const [showScrollButton, setShowScrollButton] = React.useState(false); + const [showFileTransfer, setShowFileTransfer] = React.useState(false); + + // Автоматическая прокрутка при изменении сообщений + React.useEffect(() => { + if (chatMessagesRef.current && messages.length > 0) { + const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current; + const isNearBottom = scrollHeight - scrollTop - clientHeight < 100; + if (isNearBottom) { + const smoothScroll = () => { + if (chatMessagesRef.current) { + chatMessagesRef.current.scrollTo({ + top: chatMessagesRef.current.scrollHeight, + behavior: 'smooth' + }); + } + }; + smoothScroll(); + setTimeout(smoothScroll, 50); + setTimeout(smoothScroll, 150); + } + } + }, [messages, chatMessagesRef]); + + // Обработчик скролла + const handleScroll = () => { + if (chatMessagesRef.current) { + const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current; + const isNearBottom = scrollHeight - scrollTop - clientHeight < 100; + setShowScrollButton(!isNearBottom); + } + }; + + // Прокрутка вниз по кнопке + const handleScrollToBottom = () => { + scrollToBottom(); + setShowScrollButton(false); + }; + + // Обработчик нажатия Enter + const handleKeyPress = (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + onSendMessage(); + } + }; + + // ИСПРАВЛЕНИЕ: Проверка готовности для файловых трансферов + const isFileTransferReady = () => { + if (!webrtcManager) return false; + + const connected = webrtcManager.isConnected ? webrtcManager.isConnected() : false; + const verified = webrtcManager.isVerified || false; + const hasDataChannel = webrtcManager.dataChannel && webrtcManager.dataChannel.readyState === 'open'; + + return connected && verified && hasDataChannel; + }; + + // Возврат JSX через React.createElement + return React.createElement( + 'div', + { + className: "chat-container flex flex-col", + style: { backgroundColor: '#272827', height: 'calc(100vh - 64px)' } + }, + [ + // Область сообщений + React.createElement( + 'div', + { className: "flex-1 flex flex-col overflow-hidden" }, + React.createElement( + 'div', + { className: "flex-1 max-w-4xl mx-auto w-full p-4 overflow-hidden" }, + React.createElement( + 'div', + { + ref: chatMessagesRef, + onScroll: handleScroll, + className: "h-full overflow-y-auto space-y-3 hide-scrollbar pr-2 scroll-smooth" + }, + messages.length === 0 ? + React.createElement( + 'div', + { className: "flex items-center justify-center h-full" }, + React.createElement( + 'div', + { className: "text-center max-w-md" }, + [ + React.createElement( + 'div', + { className: "w-16 h-16 bg-green-500/10 border border-green-500/20 rounded-xl flex items-center justify-center mx-auto mb-4" }, + React.createElement( + 'svg', + { className: "w-8 h-8 text-green-500", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, + React.createElement('path', { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" + }) + ) + ), + React.createElement('h3', { className: "text-lg font-medium text-gray-300 mb-2" }, "Secure channel is ready!"), + React.createElement('p', { className: "text-gray-400 text-sm mb-4" }, "All messages are protected by modern cryptographic algorithms"), + React.createElement( + 'div', + { className: "text-left space-y-2" }, + [ + ['End-to-end encryption', 'M5 13l4 4L19 7'], + ['Protection against replay attacks', 'M5 13l4 4L19 7'], + ['Integrity verification', 'M5 13l4 4L19 7'], + ['Perfect Forward Secrecy', 'M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15'] + ].map(([text, d], i) => + React.createElement( + 'div', + { key: `f${i}`, className: "flex items-center text-sm text-gray-400" }, + [ + React.createElement( + 'svg', + { + className: `w-4 h-4 mr-3 ${i === 3 ? 'text-purple-500' : 'text-green-500'}`, + fill: "none", + stroke: "currentColor", + viewBox: "0 0 24 24" + }, + React.createElement('path', { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d: d + }) + ), + text + ] + ) + ) + ) + ] + ) + ) : + messages.map((msg) => + React.createElement(EnhancedChatMessage, { + key: msg.id, + message: msg.message, + type: msg.type, + timestamp: msg.timestamp + }) + ) + ) + ) + ), + + // Кнопка прокрутки вниз + showScrollButton && + React.createElement( + 'button', + { + onClick: handleScrollToBottom, + className: "fixed right-6 w-12 h-12 bg-green-500/20 hover:bg-green-500/30 border border-green-500/30 text-green-400 rounded-full flex items-center justify-center transition-all duration-200 shadow-lg z-50", + style: { bottom: '160px' } + }, + React.createElement( + 'svg', + { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, + React.createElement('path', { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d: "M19 14l-7 7m0 0l-7-7m7 7V3" + }) + ) + ), + + // Секция передачи файлов + React.createElement( + 'div', + { + className: "flex-shrink-0 border-t border-gray-500/10", + style: { backgroundColor: '#272827' } + }, + React.createElement( + 'div', + { className: "max-w-4xl mx-auto px-4" }, + [ + React.createElement( + 'button', + { + onClick: () => setShowFileTransfer(!showFileTransfer), + className: `flex items-center text-sm text-gray-400 hover:text-gray-300 transition-colors py-4 ${showFileTransfer ? 'mb-4' : ''}` + }, + [ + React.createElement( + 'svg', + { + className: `w-4 h-4 mr-2 transform transition-transform ${showFileTransfer ? 'rotate-180' : ''}`, + fill: "none", + stroke: "currentColor", + viewBox: "0 0 24 24" + }, + showFileTransfer ? + React.createElement('path', { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d: "M5 15l7-7 7 7" + }) : + React.createElement('path', { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d: "M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13" + }) + ), + showFileTransfer ? 'Hide file transfer' : 'Send files' + ] + ), + // ИСПРАВЛЕНИЕ: Используем правильный компонент + showFileTransfer && + React.createElement(window.FileTransferComponent || (() => + React.createElement('div', { + className: "p-4 text-center text-red-400" + }, 'FileTransferComponent not loaded') + ), { + webrtcManager: webrtcManager, + isConnected: isFileTransferReady() + }) + ] + ) + ), + + // Область ввода сообщений + React.createElement( + 'div', + { className: "border-t border-gray-500/10" }, + React.createElement( + 'div', + { className: "max-w-4xl mx-auto p-4" }, + React.createElement( + 'div', + { className: "flex items-stretch space-x-3" }, + [ + React.createElement( + 'div', + { className: "flex-1 relative" }, + [ + React.createElement('textarea', { + value: messageInput, + onChange: (e) => setMessageInput(e.target.value), + onKeyDown: handleKeyPress, + placeholder: "Enter message to encrypt...", + rows: 2, + maxLength: 2000, + style: { backgroundColor: '#272827' }, + className: "w-full p-3 border border-gray-600 rounded-lg resize-none text-gray-300 placeholder-gray-500 focus:border-green-500/40 focus:outline-none transition-all custom-scrollbar text-sm" + }), + React.createElement( + 'div', + { className: "absolute bottom-2 right-3 flex items-center space-x-2 text-xs text-gray-400" }, + [ + React.createElement('span', null, `${messageInput.length}/2000`), + React.createElement('span', null, "• Enter to send") + ] + ) + ] + ), + React.createElement( + 'button', + { + onClick: onSendMessage, + disabled: !messageInput.trim(), + className: "bg-green-400/20 text-green-400 p-3 rounded-lg transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center min-h-[72px]" + }, + React.createElement( + 'svg', + { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, + React.createElement('path', { + strokeLinecap: "round", + strokeLinejoin: "round", + strokeWidth: 2, + d: "M12 19l9 2-9-18-9 18 9-2zm0 0v-8" + }) + ) + ) + ] + ) + ) + ) + ] + ); + }; + + + // Main Enhanced Application Component + const EnhancedSecureP2PChat = () => { + const [messages, setMessages] = React.useState([]); + const [connectionStatus, setConnectionStatus] = React.useState('disconnected'); + + React.useEffect(() => { + if (messages.length > 0 && chatMessagesRef.current) { + const scrollToBottom = () => { + if (chatMessagesRef.current) { + chatMessagesRef.current.scrollTo({ + top: chatMessagesRef.current.scrollHeight, + behavior: 'smooth' + }); + } + }; + + scrollToBottom(); + setTimeout(scrollToBottom, 50); + setTimeout(scrollToBottom, 150); + } + }, [messages]); + const [messageInput, setMessageInput] = React.useState(''); + const [offerData, setOfferData] = React.useState(''); + const [answerData, setAnswerData] = React.useState(''); + const [offerInput, setOfferInput] = React.useState(''); + const [answerInput, setAnswerInput] = React.useState(''); + const [keyFingerprint, setKeyFingerprint] = React.useState(''); + const [verificationCode, setVerificationCode] = React.useState(''); + const [showOfferStep, setShowOfferStep] = React.useState(false); + const [showAnswerStep, setShowAnswerStep] = React.useState(false); + const [showVerification, setShowVerification] = React.useState(false); + const [isVerified, setIsVerified] = React.useState(false); + const [securityLevel, setSecurityLevel] = React.useState(null); + + // Mutual verification states + const [localVerificationConfirmed, setLocalVerificationConfirmed] = React.useState(false); + const [remoteVerificationConfirmed, setRemoteVerificationConfirmed] = React.useState(false); + const [bothVerificationsConfirmed, setBothVerificationsConfirmed] = React.useState(false); + + // PAKE password states removed - using SAS verification instead + + // Pay-per-session state + const [sessionManager, setSessionManager] = React.useState(null); + const [showPaymentModal, setShowPaymentModal] = React.useState(false); + const [sessionTimeLeft, setSessionTimeLeft] = React.useState(0); + const [pendingSession, setPendingSession] = React.useState(null); // { type, preimage } + const [selectedSessionType, setSelectedSessionType] = React.useState(null); // 'demo', 'basic', 'premium' + + // Initialize sessionManager after loading modules + React.useEffect(() => { + if (window.PayPerSessionManager && !sessionManager) { + console.log('💰 Initializing PayPerSessionManager...'); + const newSessionManager = new window.PayPerSessionManager(); + setSessionManager(newSessionManager); + window.sessionManager = newSessionManager; + console.log('✅ PayPerSessionManager initialized successfully'); + } + }, [sessionManager]); + + + + // Global functions for accessing modal windows + React.useEffect(() => { + if (!sessionManager) return; + + window.showPaymentModal = (sessionType) => { + setShowPaymentModal(true); + // Pass the selected session type to the modal window + if (sessionType) { + console.log('Opening payment modal for session type:', sessionType); + } + }; + window.sessionManager = sessionManager; + window.forceCleanup = () => { + handleClearData(); + if (webrtcManagerRef.current) { + webrtcManagerRef.current.disconnect(); + } + if (sessionManager) { + sessionManager.cleanup(); + } + }; + + window.forceSessionReset = () => { + if (sessionManager) { + sessionManager.resetSession(); + } + setSessionTimeLeft(0); + }; + + window.forceSessionCleanup = () => { + if (sessionManager) { + sessionManager.cleanup(); + } + setSessionTimeLeft(0); + setSessionManager(null); + }; + + window.clearLogs = () => { + if (typeof console.clear === 'function') { + console.clear(); + } + }; + + return () => { + delete window.showPaymentModal; + delete window.sessionManager; + delete window.forceCleanup; + delete window.forceSessionReset; + delete window.forceSessionCleanup; + delete window.clearLogs; + }; + }, [sessionManager]); + + const webrtcManagerRef = React.useRef(null); + // Expose for modules/UI that run outside this closure (e.g., inline handlers) + // Safe because it's a ref object and we maintain it centrally here + window.webrtcManagerRef = webrtcManagerRef; + + const addMessageWithAutoScroll = React.useCallback((message, type) => { + const newMessage = { + message, + type, + id: Date.now() + Math.random(), + timestamp: Date.now() + }; + + setMessages(prev => { + const updated = [...prev, newMessage]; + + setTimeout(() => { + if (chatMessagesRef?.current) { + const container = chatMessagesRef.current; + try { + const { scrollTop, scrollHeight, clientHeight } = container; + const isNearBottom = scrollHeight - scrollTop - clientHeight < 100; + + if (isNearBottom || prev.length === 0) { + requestAnimationFrame(() => { + if (container && container.scrollTo) { + container.scrollTo({ + top: container.scrollHeight, + behavior: 'smooth' + }); + } + }); + } + } catch (error) { + console.warn('Scroll error:', error); + container.scrollTop = container.scrollHeight; + } + } + }, 50); + + return updated; + }); + }, []); + + // Update security level based on real verification + const updateSecurityLevel = React.useCallback(async () => { + if (window.isUpdatingSecurity) { + return; + } + + window.isUpdatingSecurity = true; + + try { + if (webrtcManagerRef.current) { + const level = await webrtcManagerRef.current.calculateSecurityLevel(); + setSecurityLevel(level); + + if (window.DEBUG_MODE) { + console.log('🔒 Security level updated:', { + level: level.level, + score: level.score, + sessionType: level.sessionType, + passedChecks: level.passedChecks, + totalChecks: level.totalChecks + }); + } + } + } catch (error) { + console.error('Failed to update security level:', error); + setSecurityLevel({ + level: 'ERROR', + score: 0, + color: 'red', + details: 'Verification failed' + }); + } finally { + setTimeout(() => { + window.isUpdatingSecurity = false; + }, 2000); + } + }, []); + + // Session time ticker + React.useEffect(() => { + if (!sessionManager) return; + + const timer = setInterval(() => { + if (sessionManager.hasActiveSession()) { + setSessionTimeLeft(sessionManager.getTimeLeft()); + } else { + setSessionTimeLeft(0); + } + }, 1000); + return () => clearInterval(timer); + }, [sessionManager]); + + // Session expiration handler + React.useEffect(() => { + if (!sessionManager) return; + + sessionManager.onSessionExpired = () => { + setMessages(prev => [...prev, { + message: '⏰ Session time expired. The connection will be terminated.', + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + setTimeout(() => handleDisconnect(), 3000); + }; + }, [sessionManager]); + + // Automatic activation of demo session after successful verification + React.useEffect(() => { + if (!sessionManager) return; + + // Listen to demo session verification events + const handleDemoVerification = async () => { + try { + // Check if there is an active demo session + if (sessionManager.hasActiveSession()) { + console.log('✅ Demo session already active'); + return; + } + + // Diagnose sessionManager state + console.log('🔍 SessionManager state before activation:', { + hasActiveSession: sessionManager.hasActiveSession(), + timeLeft: sessionManager.getTimeLeft(), + currentSession: sessionManager.currentSession + }); + + window.pendingDemoActivation = true; + + setTimeout(async () => { + if (window.pendingDemoActivation && sessionManager) { + let result = null; + + const demoSession = sessionManager.createDemoSessionForActivation(); + + if (!demoSession.success) { + return; + } + + result = await sessionManager.safeActivateSession( + 'demo', + demoSession.preimage, + demoSession.paymentHash + ); + + if (result && result.success) { + setSessionTimeLeft(sessionManager.getTimeLeft()); + + setMessages(prev => [...prev, { + message: `🎮 Demo session activated for ${Math.round(result.timeLeft / 60000)} minutes`, + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + + window.pendingDemoActivation = false; + } else { + window.pendingDemoActivation = false; + } + } + }, 3000); + } catch (error) { + console.error('❌ Error activating demo session automatically:', error); + } + }; + + if (connectionStatus === 'connected' && isVerified) { + setTimeout(handleDemoVerification, 1000); + } + + if (selectedSessionType === 'demo' && connectionStatus === 'connected' && isVerified) { + setTimeout(handleDemoVerification, 1000); + } + + }, [sessionManager, connectionStatus, isVerified, selectedSessionType]); + const chatMessagesRef = React.useRef(null); + + // Scroll down function + const scrollToBottom = () => { + if (chatMessagesRef.current) { + const scrollAttempt = () => { + if (chatMessagesRef.current) { + chatMessagesRef.current.scrollTo({ + top: chatMessagesRef.current.scrollHeight, + behavior: 'smooth' + }); + } + }; + scrollAttempt(); + + setTimeout(scrollAttempt, 50); + setTimeout(scrollAttempt, 150); + setTimeout(scrollAttempt, 300); + + requestAnimationFrame(() => { + setTimeout(scrollAttempt, 100); + }); + } + }; + + // PAKE password functions removed - using SAS verification instead + + React.useEffect(() => { + // Prevent multiple initializations + if (webrtcManagerRef.current) { + console.log('⚠️ WebRTC Manager already initialized, skipping...'); + return; + } + + const handleMessage = (message, type) => { + // Дополнительная проверка на файловые и системные сообщения + if (typeof message === 'string' && message.trim().startsWith('{')) { + try { + const parsedMessage = JSON.parse(message); + const blockedTypes = [ + 'file_transfer_start', + 'file_transfer_response', + 'file_chunk', + 'chunk_confirmation', + 'file_transfer_complete', + 'file_transfer_error', + 'heartbeat', + 'verification', + 'verification_response', + 'verification_confirmed', + 'verification_both_confirmed', + 'peer_disconnect', + 'key_rotation_signal', + 'key_rotation_ready', + 'security_upgrade' + ]; + if (parsedMessage.type && blockedTypes.includes(parsedMessage.type)) { + console.log(`🛑 Blocked system/file message from chat: ${parsedMessage.type}`); + return; // Не показываем системные и файловые сообщения в чате + } + } catch (parseError) { + // Не JSON - это нормально для обычных текстовых сообщений + } + } + + addMessageWithAutoScroll(message, type); + }; + + const handleStatusChange = (status) => { + console.log('handleStatusChange called with status:', status); + setConnectionStatus(status); + + if (status === 'connected') { + document.dispatchEvent(new CustomEvent('new-connection')); + + // Не скрываем верификацию при 'connected' - только при 'verified' + // setIsVerified(true); + // setShowVerification(false); + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } else if (status === 'verifying') { + console.log('Setting showVerification to true for verifying status'); + setShowVerification(true); + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } else if (status === 'verified') { + setIsVerified(true); + setShowVerification(false); + setBothVerificationsConfirmed(true); + // CRITICAL: Set connectionStatus to 'connected' to show chat + setConnectionStatus('connected'); + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } else if (status === 'connecting') { + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } else if (status === 'disconnected') { + // При разрыве соединения очищаем все данные + setConnectionStatus('disconnected'); + setIsVerified(false); + setShowVerification(false); + + // Dispatch disconnected event for SessionTimer + document.dispatchEvent(new CustomEvent('disconnected')); + + // Clear verification states + setLocalVerificationConfirmed(false); + setRemoteVerificationConfirmed(false); + setBothVerificationsConfirmed(false); + + // Clear connection data + setOfferData(null); + setAnswerData(null); + setOfferInput(''); + setAnswerInput(''); + setShowOfferStep(false); + setShowAnswerStep(false); + setKeyFingerprint(''); + setVerificationCode(''); + setSecurityLevel(null); + + // Reset session and timer + if (sessionManager && sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + setHasActiveSession(false); + } + + // Return to main page after a short delay + setTimeout(() => { + setConnectionStatus('disconnected'); + setShowVerification(false); + setOfferData(null); + setAnswerData(null); + setOfferInput(''); + setAnswerInput(''); + setShowOfferStep(false); + setShowAnswerStep(false); + setMessages([]); + }, 1000); + + // Не очищаем консоль при разрыве соединения + // чтобы пользователь мог видеть ошибки + } else if (status === 'peer_disconnected') { + if (sessionManager && sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + setHasActiveSession(false); + } + + document.dispatchEvent(new CustomEvent('peer-disconnect')); + + // A short delay before clearing to display the status + setTimeout(() => { + setKeyFingerprint(''); + setVerificationCode(''); + setSecurityLevel(null); + setIsVerified(false); + setShowVerification(false); + setConnectionStatus('disconnected'); + + // Clear verification states + setLocalVerificationConfirmed(false); + setRemoteVerificationConfirmed(false); + setBothVerificationsConfirmed(false); + + // Clear connection data + setOfferData(null); + setAnswerData(null); + setOfferInput(''); + setAnswerInput(''); + setShowOfferStep(false); + setShowAnswerStep(false); + setMessages([]); + + // Не очищаем консоль при отключении пира + // чтобы сохранить историю соединения + // if (typeof console.clear === 'function') { + // console.clear(); + // } + + setSessionManager(null); + }, 2000); + } + }; + + const handleKeyExchange = (fingerprint) => { + console.log('handleKeyExchange called with fingerprint:', fingerprint); + if (fingerprint === '') { + setKeyFingerprint(''); + } else { + setKeyFingerprint(fingerprint); + console.log('Key fingerprint set in UI:', fingerprint); + } + }; + + const handleVerificationRequired = (code) => { + console.log('handleVerificationRequired called with code:', code); + if (code === '') { + setVerificationCode(''); + setShowVerification(false); + } else { + setVerificationCode(code); + setShowVerification(true); + console.log('Verification code set, showing verification UI'); + } + }; + + const handleVerificationStateChange = (state) => { + console.log('handleVerificationStateChange called with state:', state); + setLocalVerificationConfirmed(state.localConfirmed); + setRemoteVerificationConfirmed(state.remoteConfirmed); + setBothVerificationsConfirmed(state.bothConfirmed); + }; + + // Callback for handling response errors + const handleAnswerError = (errorType, errorMessage) => { + if (errorType === 'replay_attack') { + // Reset the session upon replay attack + if (sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + } + setPendingSession(null); + + addMessageWithAutoScroll('💡 Data is outdated. Please create a new invitation or use a current response code.', 'system'); + + if (typeof console.clear === 'function') { + console.clear(); + } + } else if (errorType === 'security_violation') { + // Reset the session upon security breach + if (sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + } + setPendingSession(null); + + addMessageWithAutoScroll(`🔒 Security breach: ${errorMessage}`, 'system'); + + if (typeof console.clear === 'function') { + console.clear(); + } + } + }; + + // Create WebRTC Manager only once + console.log('🔧 Initializing WebRTC Manager...'); + + if (typeof console.clear === 'function') { + console.clear(); + } + + webrtcManagerRef.current = new EnhancedSecureWebRTCManager( + handleMessage, + handleStatusChange, + handleKeyExchange, + handleVerificationRequired, + handleAnswerError, + handleVerificationStateChange + ); + + handleMessage('🚀 SecureBit.chat Enhanced Security Edition v4.02.985 - ECDH + DTLS + SAS initialized. Ready to establish a secure connection with ECDH key exchange, DTLS fingerprint verification, and SAS authentication to prevent MITM attacks.', 'system'); + + const handleBeforeUnload = (event) => { + if (event.type === 'beforeunload' && !isTabSwitching) { + console.log('🔌 Page unloading (closing tab) - sending disconnect notification'); + + if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) { + try { + webrtcManagerRef.current.sendSystemMessage({ + type: 'peer_disconnect', + reason: 'user_disconnect', + timestamp: Date.now() + }); + } catch (error) { + console.log('Could not send disconnect notification:', error.message); + } + + setTimeout(() => { + if (webrtcManagerRef.current) { + webrtcManagerRef.current.disconnect(); + } + }, 100); + } else if (webrtcManagerRef.current) { + webrtcManagerRef.current.disconnect(); + } + } else if (isTabSwitching) { + console.log('📱 Tab switching detected - NOT disconnecting'); + event.preventDefault(); + event.returnValue = ''; + } + }; + + window.addEventListener('beforeunload', handleBeforeUnload); + + let isTabSwitching = false; + let tabSwitchTimeout = null; + + const handleVisibilityChange = () => { + if (document.visibilityState === 'hidden') { + console.log('📱 Page hidden (tab switch) - keeping connection alive'); + isTabSwitching = true; + + if (tabSwitchTimeout) { + clearTimeout(tabSwitchTimeout); + } + + tabSwitchTimeout = setTimeout(() => { + isTabSwitching = false; + }, 5000); + + } else if (document.visibilityState === 'visible') { + console.log('📱 Page visible (tab restored) - connection maintained'); + isTabSwitching = false; + + if (tabSwitchTimeout) { + clearTimeout(tabSwitchTimeout); + tabSwitchTimeout = null; + } + } + }; + + document.addEventListener('visibilitychange', handleVisibilityChange); + + // Setup file transfer callbacks + if (webrtcManagerRef.current) { + webrtcManagerRef.current.setFileTransferCallbacks( + // Progress callback + (progress) => { + console.log('File progress:', progress); + }, + + // File received callback + (fileData) => { + const sizeMb = Math.max(1, Math.round((fileData.fileSize || 0) / (1024 * 1024))); + const downloadMessage = React.createElement('div', { + className: 'flex items-center space-x-2' + }, [ + React.createElement('span', { key: 'label' }, `📥 File received: ${fileData.fileName} (${sizeMb} MB)`), + React.createElement('button', { + key: 'btn', + className: 'px-3 py-1 rounded bg-blue-600 hover:bg-blue-700 text-white text-xs', + onClick: async () => { + try { + const url = await fileData.getObjectURL(); + const a = document.createElement('a'); + a.href = url; + a.download = fileData.fileName; + a.click(); + // Даем браузеру время начать загрузку, затем освобождаем URL + setTimeout(() => fileData.revokeObjectURL(url), 15000); + } catch (e) { + console.error('Download failed:', e); + addMessageWithAutoScroll(`❌ File upload error: ${String(e?.message || e)}`, 'system'); + } + } + }, 'Download') + ]); + + addMessageWithAutoScroll(downloadMessage, 'system'); + }, + + // Error callback + (error) => { + console.error('File transfer error:', error); + + if (error.includes('Connection not ready')) { + addMessageWithAutoScroll(`⚠️ File transfer error: connection not ready. Try again later.`, 'system'); + } else if (error.includes('File too large')) { + addMessageWithAutoScroll(`⚠️ File is too big. Maximum size: 100 MB`, 'system'); + } else { + addMessageWithAutoScroll(`❌ File transfer error: ${error}`, 'system'); + } + } + ); + } + + return () => { + window.removeEventListener('beforeunload', handleBeforeUnload); + document.removeEventListener('visibilitychange', handleVisibilityChange); + + if (tabSwitchTimeout) { + clearTimeout(tabSwitchTimeout); + tabSwitchTimeout = null; + } + + if (webrtcManagerRef.current) { + console.log('🧹 Cleaning up WebRTC Manager...'); + webrtcManagerRef.current.disconnect(); + webrtcManagerRef.current = null; + } + }; + }, []); // Empty dependency array to run only once + + const ensureActiveSessionOrPurchase = async () => { + if (sessionManager.hasActiveSession()) return true; + if (pendingSession) return true; + setShowPaymentModal(true); + return false; + }; + + const handleCreateOffer = async () => { + try { + console.log('🎯 handleCreateOffer called'); + const ok = await ensureActiveSessionOrPurchase(); + if (!ok) return; + + setOfferData(''); + setShowOfferStep(false); + + console.log('🎯 Calling createSecureOffer...'); + const offer = await webrtcManagerRef.current.createSecureOffer(); + console.log('🎯 createSecureOffer returned:', offer ? 'success' : 'null'); + + // Store offer data directly (no encryption needed with SAS) + setOfferData(offer); + setShowOfferStep(true); + + const existingMessages = messages.filter(m => + m.type === 'system' && + (m.message.includes('Secure invitation created') || m.message.includes('Send the encrypted code')) + ); + + if (existingMessages.length === 0) { + setMessages(prev => [...prev, { + message: '🔐 Secure invitation created and encrypted!', + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + + setMessages(prev => [...prev, { + message: '📤 Send the invitation code to your interlocutor via a secure channel (voice call, SMS, etc.)..', + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + + } + + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } catch (error) { + setMessages(prev => [...prev, { + message: `❌ Error creating invitation: ${error.message}`, + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + } + }; + + const handleCreateAnswer = async () => { + try { + if (!offerInput.trim()) { + setMessages(prev => [...prev, { + message: '⚠️ You need to insert the invitation code from your interlocutor.', + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + return; + } + + try { + setMessages(prev => [...prev, { + message: '🔄 Processing the secure invitation...', + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + + setAnswerData(''); + setShowAnswerStep(false); + + let offer; + try { + // Parse the offer data directly (no decryption needed with SAS) + offer = JSON.parse(offerInput.trim()); + } catch (parseError) { + throw new Error(`Invalid invitation format: ${parseError.message}`); + } + + if (!offer || typeof offer !== 'object') { + throw new Error('The invitation must be an object'); + } + + if (!offer.type || offer.type !== 'enhanced_secure_offer') { + throw new Error('Invalid invitation type. Expected enhanced_secure_offer'); + } + + console.log('Creating secure answer for offer:', offer); + const answer = await webrtcManagerRef.current.createSecureAnswer(offer); + console.log('Secure answer created:', answer); + + // Store answer data directly (no encryption needed with SAS) + setAnswerData(answer); + setShowAnswerStep(true); + + const existingResponseMessages = messages.filter(m => + m.type === 'system' && + (m.message.includes('Secure response created') || m.message.includes('Send the response')) + ); + + if (existingResponseMessages.length === 0) { + setMessages(prev => [...prev, { + message: '✅ Secure response created!', + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + + setMessages(prev => [...prev, { + message: '📤 Send the response code to the initiator via a secure channel..', + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + + } + + // Update security level after creating answer + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } catch (error) { + console.error('Error in handleCreateAnswer:', error); + setMessages(prev => [...prev, { + message: `❌ Error processing the invitation: ${error.message}`, + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + } + } catch (error) { + console.error('Error in handleCreateAnswer:', error); + setMessages(prev => [...prev, { + message: `❌ Invitation processing error: ${error.message}`, + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + } + }; + + const handleConnect = async () => { + try { + if (!answerInput.trim()) { + setMessages(prev => [...prev, { + message: '⚠️ You need to insert the response code from your interlocutor.', + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + return; + } + + try { + setMessages(prev => [...prev, { + message: '🔄 Processing the secure response...', + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + + let answer; + try { + // Parse the answer data directly (no decryption needed with SAS) + answer = JSON.parse(answerInput.trim()); + } catch (parseError) { + throw new Error(`Invalid response format: ${parseError.message}`); + } + + if (!answer || typeof answer !== 'object') { + throw new Error('The response must be an object'); + } + + if (!answer.type || answer.type !== 'enhanced_secure_answer') { + throw new Error('Invalid response type. Expected enhanced\_secure\_answer'); + } + + await webrtcManagerRef.current.handleSecureAnswer(answer); + + if (sessionManager.canActivateSession() && pendingSession) { + const result = sessionManager.safeActivateSession(pendingSession.type, pendingSession.preimage, pendingSession.paymentHash); + if (result.success) { + setPendingSession(null); + setSessionTimeLeft(sessionManager.getTimeLeft()); + setMessages(prev => [...prev, { + message: `💰 Session activated on ${sessionManager.sessionPrices[pendingSession.type].hours}ч (${result.method})`, + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + } else { + setMessages(prev => [...prev, { + message: `❌ Session activation error: ${result.reason}`, + type: 'error', + id: Date.now(), + timestamp: Date.now() + }]); + } + } + + setMessages(prev => [...prev, { + message: '🔄 Finalizing the secure connection...', + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + + // Update security level after handling answer + if (!window.isUpdatingSecurity) { + updateSecurityLevel().catch(console.error); + } + } catch (error) { + setMessages(prev => [...prev, { + message: `❌ Connection setup error: ${error.message}`, + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + + if (!error.message.includes('Too old') && !error.message.includes('too old')) { + setPendingSession(null); + } + } + } catch (error) { + setMessages(prev => [...prev, { + message: `❌ Connection setup error: ${error.message}`, + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + + if (!error.message.includes('сToo old') && !error.message.includes('too old')) { + setPendingSession(null); + } + } + }; + + const handleVerifyConnection = (isValid) => { + if (isValid) { + webrtcManagerRef.current.confirmVerification(); + // Mark local verification as confirmed + setLocalVerificationConfirmed(true); + } else { + setMessages(prev => [...prev, { + message: '❌ Verification rejected. The connection is unsafe! Session reset..', + type: 'system', + id: Date.now(), + timestamp: Date.now() + }]); + + // Clear verification states + setLocalVerificationConfirmed(false); + setRemoteVerificationConfirmed(false); + setBothVerificationsConfirmed(false); + setShowVerification(false); + setVerificationCode(''); + + // Reset UI to initial state + setConnectionStatus('disconnected'); + setOfferData(null); + setAnswerData(null); + setOfferInput(''); + setAnswerInput(''); + setShowOfferStep(false); + setShowAnswerStep(false); + setKeyFingerprint(''); + setSecurityLevel(null); + setIsVerified(false); + setMessages([]); + + sessionManager.resetSession(); + setSessionTimeLeft(0); + setPendingSession(null); + + // Dispatch disconnected event for SessionTimer + document.dispatchEvent(new CustomEvent('disconnected')); + + handleDisconnect(); + } + }; + + const handleSendMessage = async () => { + if (!messageInput.trim()) { + return; + } + + if (!webrtcManagerRef.current) { + return; + } + + if (!webrtcManagerRef.current.isConnected()) { + return; + } + + try { + + // Add the message to local messages immediately (sent message) + addMessageWithAutoScroll(messageInput.trim(), 'sent'); + + // Use sendMessage for simple text messages instead of sendSecureMessage + await webrtcManagerRef.current.sendMessage(messageInput); + setMessageInput(''); + } catch (error) { + const msg = String(error?.message || error); + if (!/queued for sending|Data channel not ready/i.test(msg)) { + addMessageWithAutoScroll(`❌ Sending error: ${msg}`,'system'); + } + } + }; + + const handleClearData = () => { + // Очищаем все состояния соединения + setOfferData(''); + setAnswerData(''); + setOfferInput(''); + setAnswerInput(''); + setShowOfferStep(false); + setShowAnswerStep(false); + setShowVerification(false); + setVerificationCode(''); + setIsVerified(false); + setKeyFingerprint(''); + setSecurityLevel(null); + setConnectionStatus('disconnected'); + setMessages([]); + setMessageInput(''); + + // Clear verification states + setLocalVerificationConfirmed(false); + setRemoteVerificationConfirmed(false); + setBothVerificationsConfirmed(false); + + // PAKE passwords removed - using SAS verification instead + + // Не очищаем консоль при очистке данных + // чтобы пользователь мог видеть ошибки + // if (typeof console.clear === 'function') { + // console.clear(); + // } + + // Cleanup pay-per-session state + if (sessionManager) { + sessionManager.cleanup(); + setSessionTimeLeft(0); + } + setShowPaymentModal(false); + + setPendingSession(null); + document.dispatchEvent(new CustomEvent('peer-disconnect')); + setSessionManager(null); + }; + + const handleDisconnect = () => { + if (sessionManager && sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + } + + // Cleanup pay-per-session state + if (sessionManager) { + sessionManager.cleanup(); + } + setShowPaymentModal(false); + + if (webrtcManagerRef.current) { + webrtcManagerRef.current.disconnect(); + } + + setKeyFingerprint(''); + setVerificationCode(''); + setSecurityLevel(null); + setIsVerified(false); + setShowVerification(false); + setConnectionStatus('disconnected'); + + // Clear verification states + setLocalVerificationConfirmed(false); + setRemoteVerificationConfirmed(false); + setBothVerificationsConfirmed(false); + + // Reset UI to initial state + setConnectionStatus('disconnected'); + setShowVerification(false); + setOfferData(null); + setAnswerData(null); + setOfferInput(''); + setAnswerInput(''); + setShowOfferStep(false); + setShowAnswerStep(false); + setKeyFingerprint(''); + setVerificationCode(''); + setSecurityLevel(null); + setIsVerified(false); + + setMessages([]); + + // Не очищаем консоль при отключении + // чтобы пользователь мог видеть ошибки + // if (typeof console.clear === 'function') { + // console.clear(); + // } + + document.dispatchEvent(new CustomEvent('peer-disconnect')); + document.dispatchEvent(new CustomEvent('disconnected')); + + document.dispatchEvent(new CustomEvent('session-cleanup', { + detail: { + timestamp: Date.now(), + reason: 'manual_disconnect' + } + })); + + setTimeout(() => { + if (sessionManager && sessionManager.hasActiveSession()) { + sessionManager.resetSession(); + setSessionTimeLeft(0); + } + }, 500); + + handleClearData(); + + setTimeout(() => { + setSessionManager(null); + }, 1000); + }; + + const handleSessionActivated = (session) => { + let message; + if (session.type === 'demo') { + message = `🎮 Demo session activated for 6 minutes. You can create invitations!`; + } else { + const hours = sessionManager.sessionPrices[session.type]?.hours || 0; + message = `💰 Session activated for ${hours}h. You can create invitations!`; + } + + addMessageWithAutoScroll(message, 'system'); + + }; + + React.useEffect(() => { + if (connectionStatus === 'connected' && isVerified) { + addMessageWithAutoScroll('🎉 Secure connection successfully established and verified! You can now communicate safely with full protection against MITM attacks and Perfect Forward Secrecy..', 'system'); + + } + }, [connectionStatus, isVerified]); + + const isConnectedAndVerified = connectionStatus === 'connected' && isVerified; + + React.useEffect(() => { + if (isConnectedAndVerified && sessionManager.canActivateSession() && pendingSession && connectionStatus !== 'failed') { + const result = sessionManager.safeActivateSession(pendingSession.type, pendingSession.preimage, pendingSession.paymentHash); + if (result.success) { + setPendingSession(null); + setSessionTimeLeft(sessionManager.getTimeLeft()); + let message; + if (pendingSession.type === 'demo') { + message = `🎮 Demo session activated for 6 minutes (${result.method})`; + } else { + const hours = sessionManager.sessionPrices[pendingSession.type]?.hours || 0; + message = `💰 Session activated for ${hours}h (${result.method})`; + } + + addMessageWithAutoScroll(message, 'system'); + } else { + addMessageWithAutoScroll(`❌ Session activation error: ${result.reason}`, 'error'); + } + } + }, [isConnectedAndVerified, sessionManager, pendingSession, connectionStatus]); + + return React.createElement('div', { + className: "minimal-bg min-h-screen" + }, [ + React.createElement(EnhancedMinimalHeader, { + key: 'header', + status: connectionStatus, + fingerprint: keyFingerprint, + verificationCode: verificationCode, + onDisconnect: handleDisconnect, + isConnected: isConnectedAndVerified, + securityLevel: securityLevel, + sessionManager: sessionManager, + sessionTimeLeft: sessionTimeLeft + }), + + React.createElement('main', { + key: 'main' + }, + isConnectedAndVerified + ? React.createElement(EnhancedChatInterface, { + messages: messages, + messageInput: messageInput, + setMessageInput: setMessageInput, + onSendMessage: handleSendMessage, + onDisconnect: handleDisconnect, + keyFingerprint: keyFingerprint, + isVerified: isVerified, + chatMessagesRef: chatMessagesRef, + webrtcManager: webrtcManagerRef.current + }) + : React.createElement(EnhancedConnectionSetup, { + onCreateOffer: handleCreateOffer, + onCreateAnswer: handleCreateAnswer, + onConnect: handleConnect, + onClearData: handleClearData, + onVerifyConnection: handleVerifyConnection, + connectionStatus: connectionStatus, + offerData: offerData, + answerData: answerData, + offerInput: offerInput, + setOfferInput: setOfferInput, + answerInput: answerInput, + setAnswerInput: setAnswerInput, + showOfferStep: showOfferStep, + showAnswerStep: showAnswerStep, + verificationCode: verificationCode, + showVerification: showVerification, + messages: messages, + localVerificationConfirmed: localVerificationConfirmed, + remoteVerificationConfirmed: remoteVerificationConfirmed, + bothVerificationsConfirmed: bothVerificationsConfirmed, + // PAKE passwords removed - using SAS verification instead + }) + ), + + // PAKE Password Modal removed - using SAS verification instead + + // Payment Modal + React.createElement(PaymentModal, { + key: 'payment-modal', + isOpen: showPaymentModal, + onClose: () => setShowPaymentModal(false), + sessionManager: sessionManager, + onSessionPurchased: (session) => { setPendingSession(session); handleSessionActivated({ type: session.type }); } + }) + ]); + }; + function initializeApp() { + if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureWebRTCManager) { + ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root')); + } else { + console.error('❌ Модули не загружены:', { + hasCrypto: !!window.EnhancedSecureCryptoUtils, + hasWebRTC: !!window.EnhancedSecureWebRTCManager + }); + } + } + if (typeof window !== 'undefined' && !window.initializeApp) { + window.initializeApp = initializeApp; + } + // Render Enhanced Application + ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root')); \ No newline at end of file diff --git a/src/components/ui/LightningPayment.jsx b/src/components/ui/LightningPayment.jsx index 38e41f5..71df0fa 100644 --- a/src/components/ui/LightningPayment.jsx +++ b/src/components/ui/LightningPayment.jsx @@ -39,8 +39,14 @@ const IntegratedLightningPayment = ({ sessionType, onSuccess, onCancel, paymentM setPaymentStatus('created'); if (createdInvoice.paymentRequest) { - const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=${encodeURIComponent(createdInvoice.paymentRequest)}`; - setQrCodeUrl(qrUrl); + try { + const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300, margin: 2, errorCorrectionLevel: 'M' }); + setQrCodeUrl(dataUrl); + } catch (e) { + console.warn('QR local generation failed, showing placeholder'); + const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300 }); + setQrCodeUrl(dataUrl); + } } } catch (err) { diff --git a/src/components/ui/PaymentModal.jsx b/src/components/ui/PaymentModal.jsx index 12f3318..47186a7 100644 --- a/src/components/ui/PaymentModal.jsx +++ b/src/components/ui/PaymentModal.jsx @@ -211,8 +211,14 @@ const PaymentModal = ({ isOpen, onClose, sessionManager, onSessionPurchased }) = setInvoice(createdInvoice); setPaymentStatus('created'); - const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=${encodeURIComponent(createdInvoice.paymentRequest)}`; - setQrCodeUrl(qrUrl); + try { + const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300, margin: 2, errorCorrectionLevel: 'M' }); + setQrCodeUrl(dataUrl); + } catch (e) { + console.warn('QR local generation failed, showing placeholder'); + const dataUrl = await window.generateQRCode(createdInvoice.paymentRequest, { size: 300 }); + setQrCodeUrl(dataUrl); + } const expirationTime = 15 * 60 * 1000; setTimeLeft(expirationTime); diff --git a/src/components/ui/SessionTypeSelector.jsx b/src/components/ui/SessionTypeSelector.jsx index cd944ca..80a7a3a 100644 --- a/src/components/ui/SessionTypeSelector.jsx +++ b/src/components/ui/SessionTypeSelector.jsx @@ -179,9 +179,11 @@ const SessionTypeSelector = ({ onSelectType, onCancel, sessionManager }) => { return React.createElement('div', { key: type.id, onClick: () => !isDisabled && handleTypeSelect(type.id), - className: `relative card-minimal rounded-lg p-5 border-2 transition-all ${ - selectedType === type.id ? 'border-orange-500 bg-orange-500/10' : 'border-gray-600 hover:border-orange-400' - } ${type.popular ? 'ring-2 ring-orange-500/30' : ''} ${ + className: `relative card-minimal ${selectedType === type.id ? 'card-minimal--selected' : ''} rounded-lg p-5 border-2 transition-all ${ + selectedType === type.id + ? 'border-orange-500 bg-orange-500/15 ring-2 ring-orange-400 ring-offset-2 ring-offset-black/30' + : 'border-gray-600 hover:border-orange-400' + } ${type.popular && selectedType !== type.id ? 'ring-2 ring-orange-500/30' : ''} ${ isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer' }` }, [ diff --git a/src/network/EnhancedSecureWebRTCManager.js b/src/network/EnhancedSecureWebRTCManager.js index 5c9f746..9a63360 100644 --- a/src/network/EnhancedSecureWebRTCManager.js +++ b/src/network/EnhancedSecureWebRTCManager.js @@ -1580,10 +1580,7 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida this._originalConsole?.error?.('🚨 CRITICAL: Logging system disabled due to security violations'); } } - /** - * Shim to redirect arbitrary console.log calls to _secureLog('info', ...) - * Fixed syntax errors and improved error handling - */ + _secureLogShim(...args) { try { // Validate arguments array @@ -1622,10 +1619,7 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida } } } - /** - * Redirects global console.log to this instance's secure logger - * Improved error handling and validation - */ + /** * Setup own logger without touching global console */ @@ -3378,13 +3372,10 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida const enc = new TextEncoder(); - // Соль связываем с обоими DTLS-fingerprints (в отсортированном порядке), - // чтобы SAS «привязался» к реальному транспорту и его сертификатам const salt = enc.encode( 'webrtc-sas|' + [localFP, remoteFP].sort().join('|') ); - // Подготавливаем keyMaterialRaw для использования let keyBuffer; if (keyMaterialRaw instanceof ArrayBuffer) { keyBuffer = keyMaterialRaw; @@ -3420,9 +3411,8 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida ); const dv = new DataView(bits); - // Смешиваем оба 32-битных слова и получаем 7-значный код const n = (dv.getUint32(0) ^ dv.getUint32(4)) >>> 0; - const sasCode = String(n % 10_000_000).padStart(7, '0'); // 7 символов + const sasCode = String(n % 10_000_000).padStart(7, '0'); console.log('🎯 _computeSAS computed code:', sasCode, '(type:', typeof sasCode, ')'); @@ -6947,14 +6937,7 @@ async processMessage(data) { } else if (state === 'failed') { // Do not auto-reconnect to avoid closing the session on errors this.onStatusChange('disconnected'); - // if (!this.intentionalDisconnect && this.connectionAttempts < this.maxConnectionAttempts) { - // this.connectionAttempts++; - // setTimeout(() => this.retryConnection(), 2000); - // } else { - // this.onStatusChange('disconnected'); - // // Do not call cleanupConnection automatically for 'failed' - // // to avoid closing the session on connection errors - // } + } else { this.onStatusChange(state); } @@ -9100,11 +9083,7 @@ async processMessage(data) { this.ecdsaKeyPair.privateKey, 'ECDSA' ); - - // CRITICAL: Strict validation of exported data with hard disconnect on failure - // - Any validation failure in critical security path must abort connection - // - No fallback allowed for cryptographic validation - // - Prevent bypass of security checks through syntax/validation errors + if (!ecdhPublicKeyData || typeof ecdhPublicKeyData !== 'object') { this._secureLog('error', 'CRITICAL: ECDH key export failed - invalid object structure', { operationId }); diff --git a/src/pwa/pwa-manager.js b/src/pwa/pwa-manager.js index 3e623cb..4bc37bb 100644 --- a/src/pwa/pwa-manager.js +++ b/src/pwa/pwa-manager.js @@ -1063,7 +1063,7 @@ class PWAOfflineManager { // Singleton pattern let instance = null; -const PWAOfflineManager = { +const PWAOfflineManagerAPI = { getInstance() { if (!instance) { instance = new PWAOfflineManager(); @@ -1078,9 +1078,9 @@ const PWAOfflineManager = { // Export for module use if (typeof module !== 'undefined' && module.exports) { - module.exports = PWAOfflineManager; + module.exports = PWAOfflineManagerAPI; } else if (typeof window !== 'undefined' && !window.PWAOfflineManager) { - window.PWAOfflineManager = PWAOfflineManager; + window.PWAOfflineManager = PWAOfflineManagerAPI; } // Auto-initialize when DOM is ready @@ -1088,12 +1088,12 @@ if (typeof window !== 'undefined' && !window.pwaOfflineManager) { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { if (!window.pwaOfflineManager) { - window.pwaOfflineManager = PWAOfflineManager.init(); + window.pwaOfflineManager = PWAOfflineManagerAPI.init(); } }); } else { if (!window.pwaOfflineManager) { - window.pwaOfflineManager = PWAOfflineManager.init(); + window.pwaOfflineManager = PWAOfflineManagerAPI.init(); } } } \ No newline at end of file diff --git a/src/scripts/app-boot.js b/src/scripts/app-boot.js new file mode 100644 index 0000000..19ee8b2 --- /dev/null +++ b/src/scripts/app-boot.js @@ -0,0 +1,34 @@ +import { EnhancedSecureCryptoUtils } from '../crypto/EnhancedSecureCryptoUtils.js'; +import { EnhancedSecureWebRTCManager } from '../network/EnhancedSecureWebRTCManager.js'; +import { PayPerSessionManager } from '../session/PayPerSessionManager.js'; +import { EnhancedSecureFileTransfer } from '../transfer/EnhancedSecureFileTransfer.js'; + +// Import UI components (side-effect: they attach themselves to window.*) +import '../components/ui/SessionTimer.jsx'; +import '../components/ui/Header.jsx'; +import '../components/ui/SessionTypeSelector.jsx'; +import '../components/ui/LightningPayment.jsx'; +import '../components/ui/PaymentModal.jsx'; +import '../components/ui/DownloadApps.jsx'; +import '../components/ui/FileTransfer.jsx'; + +// Expose to global for legacy usage inside app code +window.EnhancedSecureCryptoUtils = EnhancedSecureCryptoUtils; +window.EnhancedSecureWebRTCManager = EnhancedSecureWebRTCManager; +window.PayPerSessionManager = PayPerSessionManager; +window.EnhancedSecureFileTransfer = EnhancedSecureFileTransfer; + +// Mount application once DOM and modules are ready +const start = () => { + if (typeof window.initializeApp === 'function') { + window.initializeApp(); + } else if (window.DEBUG_MODE) { + console.error('initializeApp is not defined on window'); + } +}; + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', start); +} else { + start(); +} diff --git a/src/scripts/bootstrap-modules.js b/src/scripts/bootstrap-modules.js new file mode 100644 index 0000000..c79f3a7 --- /dev/null +++ b/src/scripts/bootstrap-modules.js @@ -0,0 +1,50 @@ +// Temporary bootstrap that still uses eval for JSX components fetched as text. +// Next step is to replace this with proper ESM imports of prebuilt JS. +(async () => { + try { + const timestamp = Date.now(); + const [cryptoModule, webrtcModule, paymentModule, fileTransferModule] = await Promise.all([ + import(`../crypto/EnhancedSecureCryptoUtils.js?v=${timestamp}`), + import(`../network/EnhancedSecureWebRTCManager.js?v=${timestamp}`), + import(`../session/PayPerSessionManager.js?v=${timestamp}`), + import(`../transfer/EnhancedSecureFileTransfer.js?v=${timestamp}`), + ]); + + const { EnhancedSecureCryptoUtils } = cryptoModule; + window.EnhancedSecureCryptoUtils = EnhancedSecureCryptoUtils; + const { EnhancedSecureWebRTCManager } = webrtcModule; + window.EnhancedSecureWebRTCManager = EnhancedSecureWebRTCManager; + const { PayPerSessionManager } = paymentModule; + window.PayPerSessionManager = PayPerSessionManager; + const { EnhancedSecureFileTransfer } = fileTransferModule; + window.EnhancedSecureFileTransfer = EnhancedSecureFileTransfer; + + async function loadReactComponent(path) { + const response = await fetch(`${path}?v=${timestamp}`); + if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`); + const code = await response.text(); + // eslint-disable-next-line no-eval + eval(code); + } + + await Promise.all([ + loadReactComponent('../components/ui/SessionTimer.jsx'), + loadReactComponent('../components/ui/Header.jsx'), + loadReactComponent('../components/ui/SessionTypeSelector.jsx'), + loadReactComponent('../components/ui/LightningPayment.jsx'), + loadReactComponent('../components/ui/PaymentModal.jsx'), + loadReactComponent('../components/ui/DownloadApps.jsx'), + loadReactComponent('../components/ui/FileTransfer.jsx'), + ]); + + if (typeof window.initializeApp === 'function') { + window.initializeApp(); + } else { + console.error('❌ Function initializeApp not found'); + } + } catch (error) { + console.error('❌ Module loading error:', error); + } +})(); + + diff --git a/src/scripts/fa-check.js b/src/scripts/fa-check.js new file mode 100644 index 0000000..c1f5b09 --- /dev/null +++ b/src/scripts/fa-check.js @@ -0,0 +1,47 @@ +// Global logging and function settings +window.DEBUG_MODE = true; + +// Fake function settings (for stability) +window.DISABLE_FAKE_TRAFFIC = false; // Set true to disable fake messages +window.DISABLE_DECOY_CHANNELS = false; // Set true to disable decoy channels + +// Enhanced icon loading fallback +document.addEventListener('DOMContentLoaded', function () { + // Check if Font Awesome loaded properly + function checkFontAwesome() { + const testIcon = document.createElement('i'); + testIcon.className = 'fas fa-shield-halved'; + testIcon.style.position = 'absolute'; + testIcon.style.left = '-9999px'; + testIcon.style.visibility = 'hidden'; + document.body.appendChild(testIcon); + + const computedStyle = window.getComputedStyle(testIcon, '::before'); + const content = computedStyle.content; + const fontFamily = computedStyle.fontFamily; + + document.body.removeChild(testIcon); + + if (!content || content === 'none' || content === 'normal' || (!fontFamily.includes('Font Awesome') && !fontFamily.includes('fa-solid'))) { + console.warn('Font Awesome not loaded properly, using fallback icons'); + document.body.classList.add('fa-fallback'); + return false; + } + + if (window.DEBUG_MODE) { + console.log('Font Awesome loaded successfully'); + } + return true; + } + + if (!checkFontAwesome()) { + setTimeout(function () { + if (!checkFontAwesome()) { + console.warn('Font Awesome still not loaded, using fallback icons'); + document.body.classList.add('fa-fallback'); + } + }, 2000); + } +}); + + diff --git a/src/scripts/pwa-globals.js b/src/scripts/pwa-globals.js new file mode 100644 index 0000000..6ccca6b --- /dev/null +++ b/src/scripts/pwa-globals.js @@ -0,0 +1,83 @@ +window.forceUpdateHeader = (timeLeft, sessionType) => { + const event = new CustomEvent('force-header-update', { + detail: { timeLeft, sessionType, timestamp: Date.now() }, + }); + document.dispatchEvent(event); + if (window.sessionManager && window.sessionManager.forceUpdateTimer) { + window.sessionManager.forceUpdateTimer(); + } +}; + +window.updateSessionTimer = (timeLeft, sessionType) => { + document.dispatchEvent( + new CustomEvent('session-timer-update', { + detail: { timeLeft, sessionType }, + }), + ); +}; + +document.addEventListener('session-activated', (event) => { + if (window.updateSessionTimer) { + window.updateSessionTimer(event.detail.timeLeft, event.detail.sessionType); + } + if (window.forceUpdateHeader) { + window.forceUpdateHeader(event.detail.timeLeft, event.detail.sessionType); + } + if (window.webrtcManager && window.webrtcManager.handleSessionActivation) { + if (window.DEBUG_MODE) { + console.log('🔐 Notifying WebRTC Manager about session activation'); + } + window.webrtcManager.handleSessionActivation({ + sessionId: event.detail.sessionId, + sessionType: event.detail.sessionType, + timeLeft: event.detail.timeLeft, + isDemo: event.detail.isDemo, + sessionManager: window.sessionManager, + }); + } +}); + +if (window.DEBUG_MODE) { + console.log('✅ Global timer management functions loaded'); +} + +// Inline onclick replacement for update notification button +function attachUpdateNotificationHandlers(container) { + const btn = container.querySelector('[data-action="reload"]'); + if (btn) { + btn.addEventListener('click', () => window.location.reload()); + } + const dismissBtn = container.querySelector('[data-action="dismiss-notification"]'); + if (dismissBtn) { + dismissBtn.addEventListener('click', () => { + const host = dismissBtn.closest('div'); + if (host && host.parentElement) host.parentElement.remove(); + }); + } +} + +window.showUpdateNotification = function showUpdateNotification() { + if (window.DEBUG_MODE) console.log('🆕 Showing update notification for PWA'); + const notification = document.createElement('div'); + notification.className = 'fixed top-4 left-1/2 transform -translate-x-1/2 bg-blue-500 text-white p-4 rounded-lg shadow-lg z-50 max-w-sm'; + notification.innerHTML = ` +
+ +
+
Update Available
+
SecureBit.chat v4.02.985 - ECDH + DTLS + SAS is ready
+
+ +
`; + document.body.appendChild(notification); + attachUpdateNotificationHandlers(notification); + setTimeout(() => { + if (notification.parentElement) notification.remove(); + }, 30000); +}; + +window.showServiceWorkerError = function showServiceWorkerError(error) { + console.warn('⚠️ Service Worker error:', error); +}; diff --git a/src/scripts/pwa-register.js b/src/scripts/pwa-register.js new file mode 100644 index 0000000..f0fe495 --- /dev/null +++ b/src/scripts/pwa-register.js @@ -0,0 +1,112 @@ +// PWA Service Worker Registration +if ('serviceWorker' in navigator) { + window.addEventListener('load', async () => { + try { + const registration = await navigator.serviceWorker.register('./sw.js', { + scope: './', + }); + + console.log('✅ PWA: Service Worker registered successfully'); + console.log('📡 SW Scope:', registration.scope); + + // Store registration for use in other modules + window.swRegistration = registration; + + // Listen for updates + registration.addEventListener('updatefound', () => { + console.log('🔄 PWA: Service Worker update found'); + const newWorker = registration.installing; + + newWorker.addEventListener('statechange', () => { + if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { + console.log('🆕 PWA: New version available'); + + const isPWAInstalled = + window.matchMedia('(display-mode: standalone)').matches || + window.navigator.standalone === true || + (window.pwaInstallPrompt && window.pwaInstallPrompt.isInstalled); + + if (isPWAInstalled) { + // If this is PWA, show update notification + if (typeof window.showUpdateNotification === 'function') { + window.showUpdateNotification(); + } + } else { + // If this is browser, show install prompt + if (window.pwaInstallPrompt && !window.pwaInstallPrompt.isInstalled) { + setTimeout(() => { + window.pwaInstallPrompt.showInstallOptions(); + }, 2000); + } + } + } + }); + }); + } catch (error) { + console.error('❌ PWA: Service Worker registration failed:', error); + if (window.DEBUG_MODE) { + setTimeout(() => { + if (typeof window.showServiceWorkerError === 'function') { + window.showServiceWorkerError(error); + } + }, 2000); + } + } + }); +} + +if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready.then((registration) => { + console.log('🎯 PWA: Service Worker ready'); + + const isPWAInstalled = + window.matchMedia('(display-mode: standalone)').matches || + window.navigator.standalone === true; + + console.log('🔍 PWA Installation Status:', { + isStandalone: isPWAInstalled, + displayMode: window.matchMedia('(display-mode: standalone)').matches, + iosStandalone: window.navigator.standalone === true, + }); + + if (window.pwaInstallPrompt && window.pwaInstallPrompt.setServiceWorkerRegistration) { + window.pwaInstallPrompt.setServiceWorkerRegistration(registration); + if (isPWAInstalled && !window.pwaInstallPrompt.isInstalled) { + console.log('✅ PWA already installed, updating status'); + window.pwaInstallPrompt.isInstalled = true; + window.pwaInstallPrompt.hideInstallPrompts(); + } + } + + if (window.pwaOfflineManager && window.pwaOfflineManager.setServiceWorkerRegistration) { + window.pwaOfflineManager.setServiceWorkerRegistration(registration); + } + }); + + // Listen to Service Worker messages + navigator.serviceWorker.addEventListener('message', (event) => { + console.log('📨 Message from Service Worker:', event.data); + if (event.data && event.data.type === 'SW_ACTIVATED') { + console.log('🔄 Service Worker activated, checking for updates...'); + + const isPWAInstalled = + window.matchMedia('(display-mode: standalone)').matches || + window.navigator.standalone === true || + (window.pwaInstallPrompt && window.pwaInstallPrompt.isInstalled); + + if (isPWAInstalled) { + setTimeout(() => { + if (typeof window.showUpdateNotification === 'function') { + window.showUpdateNotification(); + } + }, 1000); + } else { + if (window.pwaInstallPrompt && !window.pwaInstallPrompt.isInstalled) { + setTimeout(() => { + window.pwaInstallPrompt.showInstallOptions(); + }, 2000); + } + } + } + }); +} diff --git a/src/scripts/qr-local.js b/src/scripts/qr-local.js new file mode 100644 index 0000000..3acdfea --- /dev/null +++ b/src/scripts/qr-local.js @@ -0,0 +1,13 @@ +// Local QR generator adapter (no external CDNs) +// Exposes: window.generateQRCode(text, { size?: number, margin?: number, errorCorrectionLevel?: 'L'|'M'|'Q'|'H' }) + +import * as QRCode from 'qrcode'; + +async function generateQRCode(text, opts = {}) { + const size = opts.size || 300; + const margin = opts.margin ?? 2; + const errorCorrectionLevel = opts.errorCorrectionLevel || 'M'; + return await QRCode.toDataURL(text, { width: size, margin, errorCorrectionLevel }); +} + +window.generateQRCode = generateQRCode; diff --git a/src/styles/components.css b/src/styles/components.css index b25e972..fb0bd61 100644 --- a/src/styles/components.css +++ b/src/styles/components.css @@ -201,6 +201,12 @@ main { border: 1px solid rgba(75, 85, 99, 0.2); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); } +/* Selected state override (higher precedence than Tailwind bg-*) */ +.card-minimal--selected { + background: rgba(249, 115, 22, 0.15) !important; /* orange-500 @ 0.15 */ + border-color: rgba(249, 115, 22, 1) !important; /* border-orange-500 */ + box-shadow: 0 0 0 2px rgba(249, 115, 22, 0.3) !important; /* soft ring */ +} /* .card-minimal:hover { border-color: rgba(249, 115, 22, 0.3); transform: translateY(-1px); diff --git a/src/styles/tw-input.css b/src/styles/tw-input.css new file mode 100644 index 0000000..b2e3de1 --- /dev/null +++ b/src/styles/tw-input.css @@ -0,0 +1,4 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + diff --git a/tailwind.config.json b/tailwind.config.json new file mode 100644 index 0000000..24f3fe3 --- /dev/null +++ b/tailwind.config.json @@ -0,0 +1 @@ +{"content":["./index.html","./dist/app.js","./src/**/*.js","./src/**/*.jsx"],"safelist":[{"pattern":"^(bg|text|border|ring|from|to|via)-(red|green|blue|yellow|orange|purple|emerald|cyan|gray|white|black)(-|$)"},{"pattern":"^(bg|text|border|ring)-(gray|slate|zinc|neutral|stone)-(50|100|200|300|400|500|600|700|800|900)$"},{"pattern":"^(bg|text|border|ring)-(orange|blue|green|yellow|red|purple|emerald|cyan)-(100|200|300|400|500|600|700)$"},{"pattern":"^(bg|text|border|ring)-.*\/(10|20|30|40|50|60|70|80|90)$"},{"pattern":"^(w|h|min-w|min-h|max-w|max-h)-\[.*\]$"},{"pattern":"^(top|right|bottom|left)-\[.*\]$"},{"pattern":"^(translate|skew|scale|rotate)-.*$"},{"pattern":"^(opacity|shadow|rounded|flex|grid|gap|p|px|py|pt|pr|pb|pl|m|mx|my|mt|mr|mb|ml)-.*$"}],"theme":{"extend":{}},"plugins":[]} diff --git a/tools/tailwindcss.exe b/tools/tailwindcss.exe new file mode 100644 index 0000000..316248f Binary files /dev/null and b/tools/tailwindcss.exe differ